如何用 fread 填充 malloc 的缓冲区?

How to fill malloc'd buffer with fread?

对于长代码表示歉意,但是就像汇编一样:

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] call [open]: d:\asmplus\tsources\s1.txt
[FILE] ret [open]: 2002397536
[FILE] call [seek]: 2002397536
[FILE] ret [seek]: 0
[FILE] call [size]: 6
[FILE] call [read]: 0
[FILE] call [close]: 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 假设:

Parameters:
* ptr -- This is the pointer to a block of memory with a minimum size of size*nmemb bytes
* size -- This is the size in bytes of each element to be read.
* nmemb -- This is the number of elements, each one with a size of size bytes.
* stream -- This is the pointer to a FILE object that specifies an input stream.

... size 将是 1 个字节(字符大小)并且 nmemb 将是缓冲区 malloc 的大小。

首先调用和分配 malloc 缓冲区,然后调用 fread 填充缓冲区,我做错了什么?

更新
添加代码以返回源文件的开头后,我正在读取字节。然而,现在似乎有一些问题引发了一些问题。这是输出:

[FILE] call [read]: 1
[FILE] ret [1 + 2;r]: 6

文件 s1.txt 包含 1 + 2;,这是在第 2 行正确报告的 6 个字节。但是 fread 显然报告说它只读取了 1 个字节?我应该在 fread 的调用中使用 fsz + 1 来摆脱 [1 + 2;r] 中的 r 吗?

the documentationprintf:

Return Value
On success, the total number of characters written is returned.

基于此,此代码不正确:

    call    _printf
    add     esp,    12

    mov     [fsz],  eax

您在 fsz 中保存的是 printf 中的 return 值,即字符串 "[FILE] call [size]: 6".

的长度

看起来你在阅读文件之前并没有回到文件的开头。因此,如果您尝试从末尾读取,您将获得 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

The file s1.txt contains 1 + 2; which is 6 bytes correctly reported on the 2nd line. But fread is apparently reporting that it only read 1 byte?

不,fread 报告它读取了 1 个 6 字节的结构。你可能想要这个:

    push    DWORD   [fh]
    push    DWORD   [fsz]
    push    DWORD   1                ; Note.. swapped!!!
    push    DWORD   [buffer]
    call    _fread
    add     esp,    16

对于缓冲区末尾的字节 -- 您正在从文件中读取 6 个字节,但 printf 需要一个以空字符结尾的字符串。如果你想解决这个问题,分配一个额外的字节 space,并在调用 printf 之前将最后一个字节设置为 '\0'。