Reputation: 79
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
Upvotes: 0
Views: 740
Reputation: 28828
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
Upvotes: 1