Here is my short assem开发者_开发技巧bly program:
; This code has been generated by the 7Basic
; compiler <http://launchpad.net/7basic>
extern printf
; Initialized data
SECTION .data
f_0 dd 5.5
printf_f: db "%f",10,0
SECTION .text
; Code
global main
main:
push ebp
mov ebp,esp
push dword [f_0]
push printf_f
call printf
add esp,8
mov esp,ebp
pop ebp
mov eax,0
ret
What the program is supposed to do is print 5.5, but it prints:
-4101885043414705786563701568963176764603483495211119243453355953219830430011006780068899468997203661787555969981250050126586203424320244681571103387315766489883301796219461838644670607029711305942610787622864198879363376953745160639821663444829839767678538571371627347101810056161000273217639447052410683392.000000
What on earth am I doing wrong? The code is pushing the two arguments to printf()
and then calling it. Nothing complicated.
Update: I was a little premature in thinking I had fixed this. I have updated the code.
The instruction push f_0
pushes the address of f_0 on the stack, not the 5.5 in memory there, so the printf routine will take the address, plus the saved ebp (the next 4 bytes on the stack) and interpret the bits as a double and print it out. That turns out to be a very large number, as you see.
You need to load 8 bytes from f_0
and push those. something like
move eax, f_0
push dword ptr [eax+4]
push dword ptr [eax]
edit
You need to push 8 bytes as fp64 values are 8 bytes. fp64 is all that printf knows how to print -- in fact fp64 is all that C knows how to pass to functions or operate on. fp32 value can only be loaded from and stored to memory, but are always implicitly converted to fp64 (or larger) before being operated on. If you want to load an fp32 value, convert it fp64, and push it on the stack, you can use
fld dword ptr [f_0]
sub esp, 8
fstp qword ptr [esp]
This actually loads an fp32 value and converts it to fp80 (the x87's internal format), then converts that fp80 value to fp64 and stores it on the stack.
精彩评论