2015-04-20 191 views
0

道歉長碼,但這樣的,因爲它是與組件:如何用fread填充malloc'd緩衝區?

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]通話[開]:d:\ asmplus \ tsources \ s1.txt
[FILE] RET [開]:2002397536
[FILE]通話[尋求]:2002397536
[FILE] RET [尋求]:0
[FILE]通話[大小]:6
[FILE]通話[讀]: 0
[FILE]通話[緊密]:0

基於@邁克爾的響應
我加入另外的輸出(在上面的代碼中未示出)校正的輸出,產生下列操作:

[FILE] RET [╨9=]:6

...下面的fread呼叫:

push DWORD [fsz] 
push DWORD [buffer] 
push DWORD mret 
call _printf 
add  esp, 12 

顯然 [fsz]從6(字節)的正確值改變爲 [buffer](20字節)基於定義 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)我期望 EAX包含的字節數長度加上2

讀。

相對片段:

; 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 bytes
* size - 這是要讀取的每個元素的大小(以字節爲單位)。
* nmemb - 這是元素的數量,每個元素的大小都是字節大小。
* stream - 這是指向指定輸入流的FILE對象的指針。

... size將是1字節(字符大小)和nmemb將是malloc'd緩衝區的大小。

我在做什麼錯在第一次調用和分配malloc'd緩衝區,第二,填寫與fread的呼叫嗎?

更新
添加代碼,以尋求回源文件的開頭後,我讀的字節數。但是,似乎有些事情現在引發了一些問題。下面是輸出:

[FILE]通話[讀]:1
[FILE] RET [1 + 2; R]:6

文件s1.txt包含1 + 2;這是第二行正確報告了6個字節。但fread顯然報告它只讀取1個字節?在撥打fread時,我是否應該使用fsz + 1來擺脫[1 + 2;r]中的r

+0

您已使用'fseek'定位到文件末尾,因此不會讀取任何字節。更好的重新定位到文件的開頭;) – Jester

+0

噢,我現在覺得比當我開始這段旅程時要笨拙。幸運的是,我可以舒舒服服地嘲笑自己。 – IAbstract

回答

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'。

+0

好的,這已經解決了最初的問題,但現在我看到了一些奇怪的東西,雖然我看到了文件的輸出(1 + 2;)參見編輯的問題(底部 - 更新)的解釋。 – IAbstract

+0

奇怪的東西?需要更多的信息,如果你需要幫助:) – jtlim

+0

看到問題的更新。 :) – IAbstract

0

the documentationprintf

返回值
如果成功,則返回寫入的字符總數。

此基礎上,這個代碼不正確:

call _printf 
    add  esp, 12 

    mov  [fsz], eax 

什麼你在fsz節能是從printf的返回值,即串"[FILE] call [size]: 6"的長度。

+0

好吧,我已更正了'mov'語句的位置,以便輸出正確。但是這仍然不能解決填充緩衝區的問題。 :) – IAbstract