题
这是我的 短的 装配程序:
; 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()
然后打电话。没什么复杂的。
更新: 我以为我已经修复了这一点还为时过早。我已经更新了代码。
解决方案
指令 push f_0
按堆栈上的F_0的地址,而不是其中的内存中的5.5,因此PrintF例程将采用该地址,再加上保存的EBP(堆栈上的下4个字节),并将其解释为双重并将其打印出来。如您所见,事实证明这是一个非常大的数字。
您需要从中加载8个字节 f_0
并推。就像是
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并将其存储在堆栈中。