为长代码道歉,但就像汇编一样:
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:\ asmplus \ tsources \ s1.txt
[FILE] ret [open]:2002397536
[FILE]致电[寻求]:2002397536
[FILE] ret [seek]:0
[FILE]调用[size]:6
[FILE]调用[read]:0
[文件]调用[关闭]:0
根据@ Michael的回复更正输出
我添加了一个额外的输出(上面的代码中没有显示),产生以下内容:
[FILE] ret [╨9=]:6
...跟随fread
电话:
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
我假设来自description here:
参数:
* ptr - 这是指向具有最小大小的内存块的指针 大小* nmemb字节
* size - 这是要读取的每个元素的大小(以字节为单位) * nmemb - 这是元素的数量,每个元素的大小都是字节大小 * stream - 这是指向输入流的FILE对象的指针。
...... size
将是1字节(字符大小),nmemb
将是malloc'd缓冲区的大小。
我在调用和分配malloc
'缓冲区时首先做错了什么,其次,在调用fread
时填写了什么?
更新
在添加代码以寻找源文件的开头之后,我正在读取字节。但是,现在似乎有些问题引发了一些问题。这是输出:
[FILE]调用[read]:1
[FILE] ret [1 + 2; r]:6
文件s1.txt包含1 + 2;
,它在第二行上正确报告了6个字节。但是fread
显然报告它只读取1个字节?我应该在fsz
的调用中使用fread
+ 1来摆脱r
中的[1 + 2;r]
吗?
答案 0 :(得分:1)
在阅读之前,您似乎没有回头查看文件的开头。因此,如果你尝试从最后读取,你将获得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需要一个以空字符结尾的字符串。如果你想解决这个问题,请分配一个额外的空格字节,并在调用printf之前将最后一个字节设置为'\ 0'。
答案 1 :(得分:0)
来自printf
的{{1}}:
返回值
成功时,将返回写入的字符总数。
基于此,此代码不正确:
call _printf
add esp, 12
mov [fsz], eax
您在fsz
中保存的内容是printf
的返回值,即字符串"[FILE] call [size]: 6"
的长度。