这是我的简短汇编程序:
; 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
该程序假设要执行的操作是打印5.5,但它会打印:
-4101885043414705786563701568963176764603483495211119243453355953219830430011006780068899468997203661787555969981250050126586203424320244681571103387315766489883301796219461838644670607029711305942610787622864198879363376953745160639821663444829839767678538571371627347101810056161000273217639447052410683392.000000
我到底在做什么?代码将两个参数推送到printf()
,然后调用它。没什么复杂的。
更新:我认为我已修复此问题还为时过早。我已经更新了代码。
答案 0 :(得分:5)
指令push f_0
在堆栈上推送f_0的地址,而不是内存中的5.5,所以printf例程将获取地址,加上保存的ebp(堆栈中接下来的4个字节)并解释将这些位作为双精度打印出来。如你所见,那就是一个非常大的数字。
您需要从f_0
加载8个字节并推送它们。
move eax, f_0
push dword ptr [eax+4]
push dword ptr [eax]
修改强>
您需要按8个字节,因为fp64值是8个字节。 fp64就是printf知道如何打印的 - 事实上fp64就是C知道如何传递给函数或进行操作。 fp32值只能从内存加载并存储到内存中,但在操作之前总是隐式转换为fp64(或更大)。如果要加载fp32值,将其转换为fp64,并将其推入堆栈,则可以使用
fld dword ptr [f_0]
sub esp, 8
fstp qword ptr [esp]
这实际上加载了一个fp32值并将其转换为fp80(x87的内部格式),然后将该fp80值转换为fp64并将其存储在堆栈中。