Gondil
Gondil

Reputation: 807

Assembly x86 read from any file and escape all special characters and get size of file in Bytes

I have an assignment from school. I have to read any file in size to 128KB and write its content on screen.

I use function 3Dh for opening specific file and then function 3Fh to read a file. I use 32KB buffer for it.

I face few problems now.

  1. Have 59KB .txt file with some text from book and also some of my codes.

When I want to get size of file in Bytes, it runs fine and result is correct.
When I want to print content of file It, prints everything to the point where occurs '$' character in file. So I need somehow escape all special characters as '$' is to print whole and any file.

  1. Have 380KB .csv file

When I print it, it is printed fine, whole file, all 380KB.
But, when I want to get size, it returns just 2186 B. When I don't close file at the end of procedure and call this procedure again and again, it returns always size in bytes as multiple of 2186 B (4372, 6558, etc.).

  1. I copied 126KB from previous .csv to another

Again print is ok (there are no '$' chars).
When I get size it returns 64063 B so again wrong result.

Here are my procedures.

buffsiz equ 32768                   ;buffer size =32KB
fnsize  equ 255                     ;filename size =255

data    segment
maxlen  db  fnsize                  ;max length of file name
len     db  ?                       ;length of filename
file    db  fnsize  dup (?)         ;file name
filesiz dd  ?                       ;dword variable of file size
buffer  db  buffsiz dup ('$')       ;32KB buffer
        ;...
data    ends

getcont proc                        ;get content of file procedure
        mov ah,3dh                  ;open file function
        mov al,0                    ;read-access bit
        call forout                 ;just bring 0 char on the end of filename
        mov dx,offset file          ;"move filename" to dx
        int 21h

        mov bx,ax                   ;move filehandler from ax to bx
buffIn: prntstr buffer              ;print content of buffer (in first iteration it is whole set to '$'
        mov ah,3fh                  ;read from file
        mov cx,buffsiz              ;how much bytes it should read from file (32768)
        mov dx,offset buffer
        int 21h

output: xchg ax,bx                  ;exchange values in ax and bx
        mov buffer[bx],'$'          ;after last read byte put '$' into buffer
        xchg ax,bx                  ;exchange registers back for next iteration
        cmp ax,0                    ;if there was no read byte stop loop
        jnz buffIn                  ;if was go to next iteration

        mov ah,3Eh                  ;close file
        int 21h

        ret
getcont endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

getsize proc
        mov word ptr[filesiz],0      ;put zero into filesize variable (dword)
        mov word ptr[filesiz]+2,0

        mov ah,3dh                  ;same as in getcont procedure
        mov al,0                    
        call forout
        mov dx,offset file          
        int 21h     

        mov bx,ax                   
bufflp: mov ah,3fh                  
        mov cx,buffsiz              
        mov dx,offset buffer
        int 21h

        add word ptr[filesiz],ax    ;add number of bytes read into filesiz variable - not certain in this
        cmp ax,0                    ;if there was no byte read end loop
        jnz bufflp                  ;if was go to next iteration

        prntstr nl                  ;new line
        prntstr velkost             ;print string about file size operation
        xor dx,dx                   ;clear ax and dx registers
        xor ax,ax
        mov ax,word ptr[filesiz]    ;move low word from filesiz(dword) variable to ax
        mov dx,word ptr[filesiz]+2  ;move high word from filesiz to dx to get filesiz=dx:ax
        call prntint                ;call procedure to print decimal number on output
        prntchr ' '                 ;print space
        prntchr 'B'                 ; print Byte unit char

        mov ah,3Eh                  ;close file
        int 21h

        ret
getsize endp

Working with TASM assembly x86.

Upvotes: 3

Views: 1764

Answers (1)

Sep Roland
Sep Roland

Reputation: 39256

I found these problems in the code you presented:

mov buffer[bx],'$'          ;after last read byte put '$' into buffer

You should enlarge the buffer by 1 byte. Now you are writing this $ past the buffer when 32768 bytes were read!

add word ptr[filesiz],ax    ;add number of bytes read into filesiz variable

The previous line will not update the dword variable filesiz! Use the following

add word ptr[filesiz],ax
adc word ptr[filesiz]+2,0

ps. You don't ever check if DOS reports an error. You should not neglect this when accessing files!

Upvotes: 3

Related Questions