为什么fopen在简单的汇编调用中失败? [警告:长装配源]

时间:2015-04-17 21:28:48

标签: assembly x86 nasm fopen

环境,赢7.使用NASM,gcc(MINGW)

我有以下非常简单的汇编源:

SECTION .data       ; initialized data
    fname:      db  "c:\asmplus\tsources\s1.txt", 0
    fread:      db  "r", 0
    mopf:       db  "[FILE] open: %s", 10, 0

SECTION .text       ; code
    extern _fopen
    extern _printf  

    push        DWORD               fname
    push        DWORD               mopf
    call        _printf
    add         esp,    8           ; clean up stack use

    mov         DWORD [esp],        fname
    mov         DWORD [esp + 4],    fread
    call        _fopen

我得到以下输出:

  

[FILE] open:c:\ asmplus \ tsources \ s1.txt

...然后是一个Windows对话框,说明应用程序崩溃了。我没有任何类型的调试器可用,所以我将其分解为最简单的源并尝试它就像这样。该文件可用且未打开。我的代码有什么特别的错误吗?

更新
完整代码添加@Jester的请求

parse.asm

SECTION .data           ; initialized data
    mend:       db  10, "*** END ***", 10, 0

    mopf:       db  "open_file", 0

    mcll:       db  "[MAIN] call %s: %s", 10, 0
    mret:       db  "[MAIN] ret: %d", 10, 0


SECTION .text use32     ; code
    extern open_file
    extern _printf

    global _main

    _main:
        ;   stash base stack pointer
        push    ebp
        mov     ebp,    esp

        mov     eax,    [ebp + 8]   ; num args
        mov     ebx,    [ebp + 12]  ; address of args (strings)
        mov     ecx,    0           ; init counter register to 0

        .do:
            push    ebp
            push    eax
            push    ecx

            mov     [c],    ecx

            ;   only expect args[1] to contain the file name
            mov     eax,    1
            cmp     eax,    [c]
            jne     .cont
            jmp     .openFile

            .cont:
                pop     ecx
                pop     eax
                pop     ebp

                add     ebx,    4       ; move to next arg
                inc     ecx             ; increment counter

                cmp     ecx,    eax
                jne     .do

        .openFile:
            push    DWORD   [ebx]
            push    DWORD   mopf
            push    DWORD   mcll
            call    _printf
            add     esp,    12

            push    DWORD   [ebx]
            call    open_file           ; should push result to eax

            mov     eax,    [ebp + 8]   ; stash file handle from stack
            mov     [fh],   eax         ; into fh variable

            add     esp,    4           ; clean up stack

            push    DWORD   [fh]
            push    DWORD   mret
            call    _printf
            add     esp,    8           ; clean up stack

        .end:
            push    DWORD   mend
            call    _printf
            ;   restore base stack pointer
            mov     esp,    ebp
            pop     ebp

SECTION .bss            ; uninitialized data
    c:      resd    1
    fh:     resd    1

fileops.asm

;   Contains file operations: 
;       open_file
;       ... TODO: read/write/close

SECTION .data       ; initialized data
    fread:      db  "r", 0

    merr:       db  "[FILE] error [%d:%d] %s", 10, 0
    mopf:       db  "[FILE] open: %s", 10, 0

SECTION .text       ; code
    extern _fopen
    extern _printf

    global open_file

    open_file:
        ;   stash base stack pointer
        push    ebp
        mov     ebp,    esp

        mov     eax,        [ebp + 8]
        mov     [fnarg],    eax
        push    DWORD       [fnarg]
        push    DWORD       mopf
        call    _printf
        add     esp,    8

        ;   open file
        push    DWORD  fread
        push    DWORD  [fnarg]
        call    _fopen
        add     esp,    8

        push    DWORD   [eax]
        xor     eax,    eax

        .done:
        ;   restore base stack pointer
        mov     esp,    ebp
        pop     ebp

        ret

SECTION .bss        ; uninitialized data
    fnarg:      resb    128             ; reserve 128 bytes for file name
    fhndl:      resd    1

当前输出:

  

D:\ asmplus>。\ exes \ parse。\ tsources \ s1.txt
  [MAIN]调用open_file:。\ tsources \ s1.txt
  [文件]打开:。\ tsources \ s1.txt
  [MAIN] ret:2

1 个答案:

答案 0 :(得分:1)

那是你的所有代码吗?如果您之后没有任何内容,它当然会崩溃,因为您不能通过call _exit或仅仅返回来正确终止您的程序。

另请注意,您要通过add esp, 8清理堆栈,这样您就不再有可用空间来尝试将参数移入。您正在覆盖堆栈中的内容,例如返回地址,如果您尝试从函数返回,则会导致问题。您可以将add向下移动到call _fopen之后,当您真的不再需要这些广告位时。

更正的版本看起来更像是:

push        DWORD               fname
push        DWORD               mopf
call        _printf

mov         DWORD [esp],        fname
mov         DWORD [esp + 4],    fread
call        _fopen
add         esp,    8           ; clean up stack use
xor         eax, eax            ; 0 return value
ret

-OR -

push        DWORD               fname
push        DWORD               mopf
call        _printf
add         esp,    8           ; clean up stack use

push        DWORD               fread
push        DWORD               fname
call        _fopen
add         esp,    8           ; clean up stack use
xor         eax, eax            ; 0 return value
ret