如何在 x86 程序集中将 64 位数字转换为字符串?
how to convert 64bit number to string in x86 assembly?
我正在寻找一种使用 32 位系统将 64 位数字转换为字符串(并且可能相反)的方法。我不是要代码,只是要一些想法。
唯一困难的部分是div在 32 位机器上将 64 位数字乘以 10。其他一切都与数字适合单个寄存器的正常情况几乎相同。
通常您可以查看 gcc 输出以获取有关如何在 asm 中执行操作的提示,但在本例中它 just calls the __udivdi3
libgcc helper function :/
如果您只是将此作为学习练习,那么您可能应该查找扩展精度 div 算法并使用它。 Here's one,来自书本,使用 Intel 语法和 16 位操作。变量名很清楚,并且有解释性文本,因此您应该能够为 32 位重新实现它。 Google 在该短语上获得更多点击率,和/或查看 libgcc 源代码。
另见
如果您要真正实现它(为了高性能):
请记住 x86 的 div
指令执行 64b/32b -> 32b division(但如果商溢出 32 位寄存器则会出错)。所以你可以检查你的高位双字的低位是否足够小,如果是这样你只需要一个 division 作为第一步来获得高位。
只要你的数字小到 divide 就可以使用单个 div
,跳出扩展精度循环并使用单个 div
每个数字。
这可能只需要一次迭代就可以减少到 32 位数字。在这一点上,您可以使用乘法逆运算将 divide 乘以 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 , %eax
ret
注意这是如何使用全乘结果的高半部分 (32bx32b->64b)。
使用乘法逆运算可能会更快,即使这意味着在 32 位机器上执行 64 x 64b -> 128b 乘法。整数 division 非常慢,几乎没有流水线,但是 integer mul is very fast on Intel CPUs.
AVX512-DQ adds a 64x64 -> 64b low multiply instruction,但这不是为了扩展精度。 AVX512-IFMA 添加了 52bx52b 低位和高位乘法指令,因此在几年内可能值得拥有一个代码路径(32 位二进制文件 运行 在具有 AVX512-IFMA 的硬件上),当前 64-52 位你的号码是全零。
我正在寻找一种使用 32 位系统将 64 位数字转换为字符串(并且可能相反)的方法。我不是要代码,只是要一些想法。
唯一困难的部分是div在 32 位机器上将 64 位数字乘以 10。其他一切都与数字适合单个寄存器的正常情况几乎相同。
通常您可以查看 gcc 输出以获取有关如何在 asm 中执行操作的提示,但在本例中它 just calls the __udivdi3
libgcc helper function :/
如果您只是将此作为学习练习,那么您可能应该查找扩展精度 div 算法并使用它。 Here's one,来自书本,使用 Intel 语法和 16 位操作。变量名很清楚,并且有解释性文本,因此您应该能够为 32 位重新实现它。 Google 在该短语上获得更多点击率,和/或查看 libgcc 源代码。
另见
如果您要真正实现它(为了高性能):
请记住 x86 的 div
指令执行 64b/32b -> 32b division(但如果商溢出 32 位寄存器则会出错)。所以你可以检查你的高位双字的低位是否足够小,如果是这样你只需要一个 division 作为第一步来获得高位。
只要你的数字小到 divide 就可以使用单个 div
,跳出扩展精度循环并使用单个 div
每个数字。
这可能只需要一次迭代就可以减少到 32 位数字。在这一点上,您可以使用乘法逆运算将 divide 乘以 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 , %eax
ret
注意这是如何使用全乘结果的高半部分 (32bx32b->64b)。
使用乘法逆运算可能会更快,即使这意味着在 32 位机器上执行 64 x 64b -> 128b 乘法。整数 division 非常慢,几乎没有流水线,但是 integer mul is very fast on Intel CPUs.
AVX512-DQ adds a 64x64 -> 64b low multiply instruction,但这不是为了扩展精度。 AVX512-IFMA 添加了 52bx52b 低位和高位乘法指令,因此在几年内可能值得拥有一个代码路径(32 位二进制文件 运行 在具有 AVX512-IFMA 的硬件上),当前 64-52 位你的号码是全零。