【问题标题】:how to convert 64bit number to string in x86 assembly?如何在 x86 程序集中将 64 位数字转换为字符串?
【发布时间】:2016-06-08 09:49:16
【问题描述】:

我正在寻找一种使用 32 位系统将 64 位数字转换为字符串(也可能反过来)的方法。我不是要代码,只是要一些想法。

【问题讨论】:

  • 这会给你一些想法 = stackoverflow.com/questions/30243848/… 。它是为 16 位和 32 位制作的,您将其修复为 64 位。尝试一下,如果您有问题,请发布您的代码,我们会为您提供帮助。
  • 您的 64 位数字到底是多少?如果它在rax 或其他一些 64 位寄存器中,则无法使用纯保护模式指令集访问高 32 位。
  • @JoseManuelAbarcaRodríguez 我不熟悉这种组装方式。我在 ubuntu 上使用 AT&T 语法。我知道转换其他尺寸很热,我对 64 位数字的困扰是如何组合它的两个 32 位部分(更高和更低)得到原始的 64 位数字。
  • @Olipro 例如,我可以将我的 64 位数字作为 .quad 类型变量,然后将低 32 位存储在 %eax 中,将高 32 位存储在 %edx 中(这就是 at&t 语法)
  • 您可以使用重复减法,因为它很容易移植到任何大小。见subsbb

标签: assembly x86 att


【解决方案1】:

唯一困难的部分是在 32 位机器上将 64 位数字除以 10。其他一切都与数字适合单个寄存器的正常情况几乎相同。

您通常可以查看 gcc 输出以获取有关如何在 asm 中执行操作的提示,但在这种情况下,它是 just calls the __udivdi3 libgcc helper function :/

如果您只是将其作为学习练习,那么您可能应该查找扩展精度的 div 算法并使用它。 Here's one,来自书中,使用 Intel 语法和 16 位操作。变量名称很清楚,并且有解释性文本,因此您应该能够为 32 位重新实现它。谷歌上那个短语以获得更多点击,和/或查看 libgcc 源代码。

另见implementing school-like division on 32bit chunks on x86


如果您要真正实现(以获得高性能):

请记住,x86 的 div 指令执行 64b/32b -> 32b 除法(但如果商溢出 32 位寄存器,则会出错)。所以你可以检查你的高位 dword 的低位是否足够小,如果是这样,第一步只需要一个除法就可以得到高位。

只要您的数字小到可以用单个 div 整除,就跳出扩展精度循环并为每个数字使用单个 div

这可能只需要一次迭代就可以减少到 32 位数字。此时,您可以使用乘法逆运算除以 10:

// from the godbolt link: gcc5.3 -O3 -m32
uint32_t div10_u32(uint32_t x) { return x/10; }
    movl    $-858993459, %edx     # 0xcccccccd
    movl    %edx, %eax            # gcc is dumb: no need for this mov.  clang avoids it
    mull    4(%esp)
    movl    %edx, %eax
    shrl    $3, %eax
    ret

注意这如何使用全乘 (32bx32b->64b) 结果的高半部分。


使用乘法逆运算可能会更快,即使这意味着在 32 位机器上进行 64 x 64b -> 128b 乘法运算。整数除法非常慢,几乎没有流水线,但是integer mul is very fast on Intel CPUs

AVX512-DQ adds a 64x64 -> 64b low multiply instruction,但这不适用于扩展精度。 AVX512-IFMA 添加了 52bx52b 低和高乘法指令,因此在几年内,当您的数字的前 64-52 位是全零。

【讨论】:

    猜你喜欢
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 2023-04-10
    • 2018-03-30
    • 2020-03-21
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多