具有 32 位程序的 x86 程序集 64 位值

x86 assembly 64-bit values with 32-bit program

提问人:Tim 提问时间:11/7/2023 最后编辑:Sep RolandTim 更新时间:11/12/2023 访问量:61

问:

如果我们将两个非常大的 32 位值相乘,结果可能最终出现在寄存器 EDX 和 EAX 中,其中 EDX 持有更高的位。

  • 我们如何对这些 64 位值执行操作并将它们打印到显示器上?

我认为存储它们只是保留两个彼此相邻的 32 位内存空间,然后首先将 EAX 存储,然后将 EDX 存储在下一个 32 位空间中。因此,在小端序的情况下,我们将首先拥有 EAX 的最低位,最后保留 EDX 的最高位,跨越两个 32 位内存空间。

  • 这是对的吗?
  • 如果是这样,那么在那之后,我们必须做些什么抽象思维才能对数字进行操作?
  • 此外,是否可以以某种方式使用 32 位函数来仅使用原始说明符(例如“%d”、“%u”或“%x”)来显示值?还是我们必须制作自己的组装过程来打印值?printf
程序集 x86 NASM 32 位-64 位 字节序

评论

1赞 Chris Dodd 11/7/2023
大多数 32 位 C 编译器/库都支持 64 位值的类型,并且它们的函数使用(或有时)作为此类型的大小修饰符(因此您可以使用 or 或 等说明符。long longprintfllL"%lld""%llu""%llx"
2赞 Peter Cordes 11/7/2023
是的,没错。看看编译器是如何用 / 添加函数参数的,例如 - godbolt.org。(如何消除 GCC/clang 程序集输出中的“噪音”?uint64_taddadcgcc -m32 -O2)
2赞 fuz 11/7/2023
对于加法/减法/比较,请使用 和 说明。对于乘法和除法,按照小学时教授的长乘法/除法,但使用 32 位“数字”。我建议你实现所有的基本运算(加法、减法、乘法、除法)来熟悉大致思路。剩下的就很容易了。哦,对于位移,使用,当然。adcsbbshldshrd
0赞 Tim 11/7/2023
我想我真正想知道的是,当我们使用 64 位寄存器时,printf 如何打印 32 位值?这在汇编代码中会是什么样子?人们如何自己创建该功能?
1赞 Peter Cordes 11/8/2023
此外,使用 DOS 显示数字在 16 位模式下显示 32 位除法,这是同样的问题。

答:

1赞 Sep Roland 11/8/2023 #1

您对存储 EDX:EAX 中的 64 位值的观察是正确的。

进一步的计算非常简单,是加法和减法:

add  eax, ebx    ; EDX:EAX + ECX:EBX
adc  edx, ecx

sub  eax, ebx    ; EDX:EAX - ECX:EBX
sbb  edx, ecx

我想我真正想知道的是,当我们使用 64 位寄存器时,printf 如何打印 32 位值?这在汇编代码中会是什么样子?人们如何自己创建该功能?

从您的评论中可以清楚地看出,您真的想自己将 64 位数字 EDX:EAX 转换为字符串。
我在如何在 EDX:EAX in Assembly 中打印乘法结果中的答案显示了如何做到这一点。
有关转换的一般方法的其他信息,请务必阅读此处提供链接的答案。不要因为提到(旧的)DOS而感到害怕。随着技术的发展,许多原则并没有太大变化......

评论

0赞 Tim 11/8/2023
太棒了,谢谢!