为什么这个简单的程序会输出这么多字符?

时间:2010-09-12 04:03:46

标签: assembly x86 printf x87

这是我的简短汇编程序:

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


更新:我认为我已修复此问题还为时过早。我已经更新了代码。

1 个答案:

答案 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并将其存储在堆栈中。