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

发布于 2024-09-18 23:07:29 字数 981 浏览 1 评论 0原文

Here is my short assembly program:

; 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

What the program is supposed to do is print 5.5, but it prints:

-4101885043414705786563701568963176764603483495211119243453355953219830430011006780068899468997203661787555969981250050126586203424320244681571103387315766489883301796219461838644670607029711305942610787622864198879363376953745160639821663444829839767678538571371627347101810056161000273217639447052410683392.000000

What on earth am I做错了吗?该代码将两个参数推送到 printf(),然后调用它。没什么复杂的。


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

Here is my short assembly program:

; 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

What the program is supposed to do is print 5.5, but it prints:

-4101885043414705786563701568963176764603483495211119243453355953219830430011006780068899468997203661787555969981250050126586203424320244681571103387315766489883301796219461838644670607029711305942610787622864198879363376953745160639821663444829839767678538571371627347101810056161000273217639447052410683392.000000

What on earth am I doing wrong? The code is pushing the two arguments to printf() and then calling it. Nothing complicated.


Update: I was a little premature in thinking I had fixed this. I have updated the code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

℉服软 2024-09-25 23:07:29

指令 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]

edit

您需要推送 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并存储它在堆栈上。

The instruction push f_0 pushes the address of f_0 on the stack, not the 5.5 in memory there, so the printf routine will take the address, plus the saved ebp (the next 4 bytes on the stack) and interpret the bits as a double and print it out. That turns out to be a very large number, as you see.

You need to load 8 bytes from f_0 and push those. something like

move eax, f_0
push dword ptr [eax+4]
push dword ptr [eax]

edit

You need to push 8 bytes as fp64 values are 8 bytes. fp64 is all that printf knows how to print -- in fact fp64 is all that C knows how to pass to functions or operate on. fp32 value can only be loaded from and stored to memory, but are always implicitly converted to fp64 (or larger) before being operated on. If you want to load an fp32 value, convert it fp64, and push it on the stack, you can use

fld dword ptr [f_0]
sub esp, 8
fstp qword ptr [esp]

This actually loads an fp32 value and converts it to fp80 (the x87's internal format), then converts that fp80 value to fp64 and stores it on the stack.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文