如何用fread填充malloc& d缓冲区?

时间:2015-04-20 12:10:46

标签: assembly malloc nasm 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]调用[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]吗?

2 个答案:

答案 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"的长度。