对长代码表示歉意,但与汇编程序一样:
SECTION .text ; code
extern _fclose
extern _fopen
extern _fread
extern _fseek
extern _ftell
extern _malloc
extern _printf
global _main
_main:
; stash base stack pointer
push ebp
mov ebp, esp
push DWORD fname
push DWORD mopf
push DWORD mcls
call _printf
add esp, 12 ; clean up stack use
; open file
push DWORD fread
push DWORD fname
call _fopen
add esp, 8
cmp eax, 0
jnz .valid
push DWORD mfnf
push DWORD mopf
jmp .error
.valid:
mov [fh], eax
; output result
push DWORD [fh]
push DWORD mopf
push DWORD mret
call _printf
add esp, 12
push DWORD [fh]
push DWORD mskf
push DWORD mcld
call _printf
add esp, 12
; C:
; fseek(fp, 0L, SEEK_END); ; set up constants: SEEK_END, SEEK_SET, etc.
push DWORD [SEEK_END]
push DWORD 0 ; 0L
push DWORD [fh] ; f_hndl
call _fseek ; ret [eax]: 0 okay; otherwise 1
add esp, 12 ; reset stack pointer
cmp eax, 0
je .success
push DWORD mske
push DWORD mskf
jmp .error
.success:
; output result
push DWORD eax
push DWORD mskf
push DWORD mret
call _printf
add esp, 12
; C:
; sz = ftell(fp); ; result to eax
push DWORD [fh]
call _ftell
add esp, 4
mov [fsz], eax
; output result
push DWORD [fsz]
push DWORD mszf
push DWORD mcld
call _printf
add esp, 12
; allocate buffer
; C:
; p* = malloc(size)
push DWORD [fsz]
call _malloc
add esp, 4
mov DWORD[buffer], eax
; read file
; size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
push DWORD [fh]
push DWORD 1
push DWORD [fsz]
push DWORD [buffer]
call _fread
add esp, 16
push DWORD eax
push DWORD mrdf
push DWORD mcld
call _printf
add esp, 12
jmp .done
.error:
push DWORD merr
call _printf
add esp, 12
.done:
push DWORD [fh]
call _fclose
push DWORD eax
push DWORD mclf
push DWORD mcld
call _printf
add esp, 16
; restore base stack pointer
mov esp, ebp
pop ebp
ret
SECTION .bss ; uninitialized data
fh: resd 1
fsz: resd 1
buffer: resb 20
电流输出:
[FILE]调用[open]:d:\asplus\tsources\s1.txt
[FILE]ret[open]:2002397536
[FILE]调用[seek]:2002398536
[FILE]ret[seek]:0
[FILE]调用[size]:6
[FILE]呼叫[read]:0
[FILE]调用[close]:0
根据@Michael的响应校正输出
我添加了一个额外的输出(上面的代码中没有显示),它产生以下结果:
[FILE]ret[╨9=]:6
。。。其遵循CCD_ 1调用:
push DWORD [fsz]
push DWORD [buffer]
push DWORD mret
call _printf
add esp, 12
显然,[fsz]
的正确值从6(字节)变为[buffer]
的长度(20字节)加2。
基于定义size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
,我期望EAX
包含读取的字节数。
相对片段:
; allocate buffer
; C:
; p* = malloc(size)
push DWORD [fsz]
call _malloc
add esp, 4
mov DWORD[bfr], eax
; read file
; size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
push DWORD [fh] ; FILE* stream (file handle)
push DWORD 1 ; size_t nmemb
push DWORD [fsz] ; size_t size
push DWORD [buffer] ; void* ptr (buffer previously malloc'd)
call _fread
add esp, 16
我从这里的描述中推测:
参数:
*ptr--这是指向最小大小内存块的指针大小为*nmmb字节
*size--这是要读取的每个元素的大小(以字节为单位)
*nmemb——这是元素的数量,每个元素的大小为字节
*stream——这是指向指定输入流的FILE对象的指针。
。。。CCD_ 6将是1字节(字符大小),而CCD_。
首先调用和分配malloc
'd缓冲区,然后用对fread
的调用填充缓冲区,我做错了什么?
更新
在添加代码以查找回源文件的开头后,我正在读取字节。然而,现在似乎有一些事情引发了几个问题。这是输出:
[FILE]调用[读取]:1
[FILE]ret[1+2;r]:6
文件s1.txt包含fread
0,在第2行正确报告了6个字节。但fread
显然报告它只读取1个字节?我应该在对fread
的调用中使用fsz
+1来消除[1 + 2;r]
中的r
吗?
在读取文件之前,您似乎没有找到文件的开头。因此,如果您尝试从末尾读取,您将获得0个字节。
即。加载项:
push DWORD 0 ; SEEK_SET = 0
push DWORD 0 ; 0L
push DWORD [fh] ; f_hndl
call _fseek ; ret [eax]: 0 okay; otherwise 1
add esp, 12 ; reset stack pointer
文件s1.txt包含1+2;正确报告的是6个字节第二行。但fread显然报告说它只读1字节
否,fread报告它读取了1个结构,共6个字节。你可能想要这个:
push DWORD [fh]
push DWORD [fsz]
push DWORD 1 ; Note.. swapped!!!
push DWORD [buffer]
call _fread
add esp, 16
对于缓冲区末尾的字节,您正在从文件中读取6个字节,但printf需要一个以null结尾的字符串。如果要修复此问题,请分配一个额外的字节空间,并在调用printf之前将最后一个字节设置为"\0"。
来自printf
:的文档
返回值
成功时,将返回写入的总字符数。
基于此,此代码不正确:
call _printf
add esp, 12
mov [fsz], eax
在fsz
中保存的是printf
的返回值,即字符串"[FILE] call [size]: 6"
的长度。