简体   繁体   中英

Assembler program crashes after call to printf

I am writing a simple function to print a float value from stack. This function is generated, so it is not optimized. Program crashes at printf call.

;input: float32 as dword ptr ebp+8
printfloat32:
 push   ebp
  mov   ebp,    esp
  sub   esp,    16
;local ptr variable k at dword ptr ebp-4
  mov   dword ptr ebp-4,    lpcstr4 ;which is "%f"

movss       xmm0,           dword ptr ebp+8
cvtss2sd    xmm0,           xmm0
  sub       esp,            8
movsd       qword ptr esp,  xmm0
 push       dword ptr ebp-4
 call       printstr
  add       esp,            12

  mov   esp,    ebp
  pop   ebp
  ret

printstr is printf. Here is the full generated code: https://pastebin.com/g0Wff0JY

Looking at the image, I see what could be a potential issue, but I don't know fasm syntax:

        call    [printstr]     ;syntax used for the first call
        ...
        call    printstr       ;syntax used for the second call that fails

If printstr is a memory based pointer to the function, then the second call syntax may be trying to make a call to where the pointer is stored, rather than calling the actual function by using the value in memory as a pointer to function.

In the case of recent versions of Visual Studio, the default printf and scanf are effectively inlined into C/C++ code, with fairly complex syntax. Rather than deal with this, there are callable legacy versions available that require this includelib statement:

        includelib      legacy_stdio_definitions.lib    ;for scanf, printf, ...

I converted the code from the question to masm syntax, change printstr to printf and tested a 32 bit build using Visual Studio 2015 on Windows 7 Pro 64 bit (the build is 32 bit so was run in 32 bit mode). I didn't have any issues with this code. I stepped through the code using debugger and didn't see any issues with how stuff was stored on the stack. I suspect the issue is with the second call to printstr without the brackets, which I corrected as part of the conversion to masm syntax.

        .data
varf    real4   123.75
lpcstr4 db      "%f",00ah,0             ;added new line
        .code
        extern  printf:near             ;instead of printstr

printfloat32 proc
        push    ebp
        mov     ebp,esp
        sub     esp,16
        mov     dword ptr [ebp-4], offset lpcstr4
        movss   xmm0,dword ptr [ebp+8]
        cvtss2sd xmm0,xmm0
        sub     esp,8
        movsd   qword ptr [esp],xmm0
        push    dword ptr [ebp-4]
        call    printf                  ;was printstr
        add     esp,12
        mov     esp,ebp
        pop     ebp
        ret
printfloat32 endp

main    proc
        push    varf            ;test printfloat32 function
        call    printfloat32
        add     esp,4
        xor     eax,eax
        ret
main    endp
        end

Using printstr as a pointer to printf. Masm doesn't need brackets, since it knows printstr is a dd (pointer to printf).

        .code
        extern  printf:near
printstr dd     printf          ;masm doesn't need brackets

printfloat32 proc
;       ...
        call    printstr        ;masm doesn't need brackets
;       ...
printfloat32 endp

If printstr was external to this source file, the masm syntax would be

        extrn   printstr:ptr    ; or extern   printstr:dword

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM