【发布时间】:2017-03-06 12:14:49
【问题描述】:
我用 TASM 程序集编写了以下代码,用于从文件中读取并使用缓冲区打印出文件内容。
缓冲区声明:
buffer db 100 dup (?), '$' ;regarding to comment, buffer is db 101 dup (?), '$'
编辑
我的程序结构是:
任务 1 要求我提供我想要读取的文件名(字符串)。
输入文件名后,task1 程序打开文件。
mov ah, 3dh
xor al, al
lea dx, fname
int 21h ;open file
jc openError
mov bx, ax
不确定,如果打开文件是正确的,因为我见过类似的打开文件的方法,但我这里没有处理程序,或者?
这里是阅读部分task2:
task2 proc
pam 10,13 ;pam is macro for printing out
read:
mov ah, 3fh
lea dx, buffer
mov cx, 100
int 21h
jc readError ;read error , jump
mov si, ax
mov buffer[si], '$'
mov ah, 09h
int 21h ;print out
cmp si, 100
je read
jmp stop ;end
openError:
pam error1
jmp stop
readError:
pam error2
stop: ret
task2 endp
我的问题是,如何使用此代码获取文件长度?我读过有一些获取文件大小的方法,但它们看起来都很复杂,我在想,当我读取文件时,我应该能够通过将读取的字符数存储在寄存器中来计算文件大小,但我不是如此确定,如果可能的话,那么我不知道如何在 tasm 中做到这一点。同样在数据段中,我需要什么变量来存储文件大小?也许一个代码 sn-p 可以帮助我通过一些有用的 cmets 来理解这个过程,它是如何工作的。感谢您的帮助。
关于答案的更新:
所以我尝试将十六进制转换为十进制,它有点工作,但我必须有一些错误,因为它适用于小文件,假设我尝试了 1kB 文件并且它工作,我在屏幕上打印了字节大小但是当我尝试像 128kB 这样更大的文件时,十进制数字不正确 - 打印大小错误,文件很大 130,862 bytes,我的转换给了我 -- MENU653261 = Enter file name。
... code from the answer ...
lea di,[buffer] ; hexa number will be written to buffer
mov word ptr [di],('0' + 'x'*256) ; with C-like "0x" prefix
add di,2 ; "0x" written at start of buffer
mov ax,dx
call AxTo04Hex ; upper word converted to hexa string
mov ax,cx
call AxTo04Hex ; lower word converted to hexa string
mov byte ptr [di],'$' ; string terminator
;HEX TO DECIMAL = my code starts here
mov cx,0
mov bx,10
loop1: mov dx,0
div bx
add dl,30h
push dx
inc cx
cmp ax,9
jg loop1
add al,30h
mov [si],al
loop2: pop ax
inc si
mov [si],al
loop loop2
; output final string to screen
mov ah,9
lea dx,[buffer]
int 21h
这是一个屏幕显示十进制值被打印出来时的样子。它与下一行混合。我试图将其移至下一行,但没有帮助。 screenshot
【问题讨论】:
-
您可以通过读取文件的内容并计数来计算文件大小,但它非常无效。通过使用某种
sys_stat调用,您可以读取有关文件的不同信息,而无需读取其全部内容(更快)。存储大小的正确类型取决于所使用的文件系统,对于常见的现代文件系统,64 位是最低要求,因此 C/C++ 中的long long或 TASM 中的qword。从您的源代码来看,它看起来像 DOS 程序集,对于 DOS FAT FS 32 位就足够了(DOS 不支持超过 4GiB 大小的文件,许多工具对于 2+GiB 文件已经失败)。 -
其实在 DOS 下还有另外一种方法,如果你不想进入“FCB”文件服务,而想继续使用“handle”变体,你可以通过@获取文件长度987654322@到文件末尾,并读取返回值。
-
@Ped7g 我只需要读取大约 1Mb 的文件,所以大文件不是问题。这只是某种学校作业。是的,我正在使用 DOS 32 位。所以你建议使用 sys_stat?
-
是的,但是我在
int 21h的描述中没有找到sys_stat-like的服务,我想大部分是通过读取目录“文件”的内容来实现的,所以那会相当一些代码。如果您只想要长度,请使用文件指针技巧(上面的服务描述链接,params al=2,cx:dx=0,dx:ax 将是文件的长度(在调试器中验证我正确理解了服务描述并且它作品:)))。那应该只是几条(~10)条指令。关于最大文件大小,如果您可以以十六进制显示它,那么正确的 uint32 很容易。在 12 月,在 16b asm 中可能有点棘手,但您可以 google... -
顺便说一句,您当前的代码正在覆盖内存,如果您在读取 100 个字节后放置
'$',则需要 101 个字节的缓冲区。