【问题标题】:Why is this simple program outputting so many characters?为什么这个简单的程序会输出这么多字符?
【发布时间】:2010-09-12 04:03:45
【问题描述】:

这是我的简短汇编程序:

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


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

【问题讨论】:

    标签: assembly x86 printf x87


    【解决方案1】:

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

    【讨论】:

    • [facepalm] 所以这就是它打印大量数字的原因!
    • f_0 一个地址。获取存储在那里的值的唯一方法是取消引用它。
    • @Gabe:我知道他是这个意思。烦人的事?我已经这样做了一次:) 为什么我要加载 8 个字节?
    • George:我很确定printf 没有标准化的打印float 的方法,因为C 会自动将float 参数转换为double。你可以编译float f = 5.5; printf("%f", f);并反汇编目标代码看看会发生什么。
    • Chris:我很确定 C 可以将 float 传递给它知道接受 float 的函数,但在这种情况下,printf 是一个可变参数(可变参数)函数,所以它不知道目标类型应该是什么。由于它不知道函数所期望的,它会恢复到旧的原型前行为,其中大多数东西都是intdouble
    猜你喜欢
    • 1970-01-01
    • 2021-02-05
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 2011-07-10
    相关资源
    最近更新 更多