Reputation: 807
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.
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.
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.).
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
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