Search code examples
assemblyfile-iobufferdosemu8086

Write to file in Assembly


I have a task to print a buffer and some other text into a file and when I use this code I get a wrong answer. Outputing a buffer is OK, it prints perfectly, but when I try to print text, declared in data, non-senses start happening. For example, when I try to print "Hello (letters )", it gives me this "Hello (9 spaces)(letters$)$". When I write 3 different procedures for each string, it prints correctly. Maybe you can help me find the problem, guys?

model small

BufSize EQU 60

.stack 100h
.data
    rez db "rez.txt", 
    Buf db BufSize dup (?)
    handle  dw ?
    Letters db 0
    brackets1 db " (letters$"
    brackets2 db ")$"
.code
start:
    MOV ax, @data
    MOV ds, ax

    MOV ah, 3Ch
    MOV cx, 0
    MOV dx, offset rez
    INT 21h              ;results file is created and opened
    MOV handle, ax

    MOV cx, 5            ;5 bytes ("Hello")
    ADD cx,10            ;10 bytes from "(letters " and ")"
    MOV bx, handle
    CALL    Write

    MOV ah, 3Eh
    MOV bx, handle
    INT 21h              ;close file

    MOV ah, 4Ch
    MOV al, 0
    INT 21h 

PROC Write
    PUSH    dx

    MOV ah, 40h
    MOV dx, offset Buf
    INT 21h          ;Write to file

    MOV ah,40h
    MOV dx,offset brackets1
    INT 21h 

    MOV ah,40h
    MOV dx,offset brackets2
    INT 21h

    POP dx
    RET
RasykBuf ENDP

END start   

Solution

  • I've added some omitted instruction and new comments; there was one compiling error that I've corrected: RasycBuf ENDP (isn't Write the name of the PROCedure ?). Whenever you do an I/O operation, you must check if it is successfully done, otherwise the next I/O's operation can generate a RUN-TIME's ERROR. I've successfully compiled this source code. However I don't know what you want it does, because the program, as said by another user, is incomplete.

    model small
    
    BufSize EQU 60
    
    .stack 100h
    .data
        rez db "rez.txt", 0       ; NULL TERMINATOR WAS OMIT.
        Buf db BufSize dup (32)   ; CHARACTERS WITHOUT A PURPOSE (SPACES).
        ;handle  dw ?             ; NOT NEEDED.
        ;Letters db 0             ; NOT USED.
        brackets1 db " (letters$"
        brackets2 db ")$"
    .code
    start:
        MOV ax, @data
        MOV ds, ax
    
        MOV ah, 3Ch
        MOV cx, 0
        MOV dx, offset rez
        ; AH      -> 3CH, CREATE A FILE WITH HANDLE.
        ; CX      -> Attribute for file:
        ;            Bit0: read-only.
        ;            Bit1: hidden.
        ;            Bit2: system.
        ;            Bit3: volume-label.
        ;            Bit4: directory.
        ;            Bit5: archive.
        ;            Bit6: UNKNOWN.
        ;            Bit7: shareable.
        ; DS:DX   -> ASCIZ file-name (with optional drive and path).
        ; OUTPUT  -> FCarry=1:       ERROR, AX= error-code;
        ;            FCarry=0: SUCCESSFULL, AX= file-handle.
        INT 21h              ; Results file is created and opened.
        JB  openfailed       ; If error, exit.
        ;MOV handle, ax      ; Not needed.
    
        ;MOV cx, 5           ; 5 bytes ("Hello")
        ;ADD cx, 10          ; 10 bytes from "(letters " and ")"
        MOV bx, ax           ; Copy file-handle into BX's reg.
        CALL    Write
    
        MOV ah, 3Eh
        ;MOV bx, handle      ; BX's reg. already contains handle.
        ; AH      -> 3EH, CLOSE A FILE WITH HANDLE.
        ; BX      -> File-handle
        ; OUTPUT  -> FCarry=1:       ERROR, AX= error-code;
        ;            FCarry=0: SUCCESSFULL.
        INT 21h              ; Close file
    
    openfailed:
        MOV ah, 4Ch
        MOV al, 0
        ; AH      -> 4CH, QUIT WITH EXIT CODE (EXIT).
        ; AL      -> EXIT CODE.
        INT 21h
    
    Write:
        ; I suppose that you want to write the content of the buffer (Buf),
        ; followed by brackets1 and brackets2 strings.
        ; NOTE: Buf CONTAINS ONLY CHARACTERS WITHOUT A PURPOSE !
        ;PUSH    dx          ; Because DX's reg. is only used here, don't need to PUSH/POP it
    
        MOV ah, 40h
        MOV cx, BufSize      ; Size of Buf
        MOV dx, offset Buf
        ;  AH     -> 40H, WRITE TO FILE WITH HANDLE
        ;  BX     -> Handle
        ;  CX     -> Buffer's size
        ;  DS:DX  -> Buffer
        ; OUTPUT  -> FCarry=1:       ERROR, AX= error-code;
        ;            FCarry=0: SUCCESSFULL, AX= num. of byte written.
        INT 21h              ; Write to file
        JB  error            ; If error, return
    
        MOV ah, 40h
        MOV cx, 10           ; Size of brackets1's string
        MOV dx, offset brackets1
        ;  AH     -> 40H, WRITE TO FILE WITH HANDLE
        ;  BX     -> Handle
        ;  CX     -> Buffer's size
        ;  DS:DX  -> Buffer
        ; OUTPUT  -> FCarry=1:       ERROR, AX= error-code;
        ;            FCarry=0: SUCCESSFULL, AX= num. of byte written.
        INT 21h
        JB  error            ; If error, return
    
        MOV ah, 40h
        MOV cx, 2            ; Size of brackets2's string
        MOV dx, offset brackets2
        ;  AH     -> 40H, WRITE TO FILE WITH HANDLE
        ;  BX     -> Handle
        ;  CX     -> Buffer's size
        ;  DS:DX  -> Buffer
        ; OUTPUT  -> FCarry=1:       ERROR, AX= error-code;
        ;            FCarry=0: SUCCESSFULL, AX= num. of byte written.
        INT 21h
    error:
        ;POP dx              ; Because DX's reg. is only used here, don't need to PUSH/POP it
        RET
    
    END start