0

这是我的简短汇编程序:

; 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()然后调用它。没什么复杂的。


更新:我认为我已经解决了这个问题还为时过早。我已经更新了代码。

4

1 回答 1

5

该指令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 并将其存储在堆栈中。

于 2010-09-12T04:12:38.497 回答