2016-06-07 50 views
-1

我正在寻找一种方法将64位数字转换为使用32位系统的字符串(也可能是其他方式)。我不是要求代码,只是要求一些想法。如何将64位数转换为x86程序集中的字符串?

+1

这会给你的想法= http://stackoverflow.com/questions/30243848/assembly-x86-date-to-number-breaking-a-string-into-smaller-sections/30244131#30244131。它用于16位和32位,您将其修复为64位。试一试,如果你有问题,发布你的代码,我们会帮助你。 –

+0

你的64位数字到底如何?如果它在'rax'或其他一些64位寄存器中,则无法使用纯保护模式指令集访问高32位。 – Olipro

+0

@JoseManuelAbarcaRodríguez我对这种装配不熟悉。我在ubuntu上使用AT&T语法。我知道转换其他大小的热门,关于64位数字的问题是如何将其两个32位部分(更高和更低)结合起来,从而得到原始的64位数字。 – sstefan

回答

3

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

通常你可以看看gcc的输出如何做事ASM提示,但在这种情况下,它just calls the __udivdi3 libgcc helper function:/

如果你只是在做这个作为一个学习锻炼的时候,那么很可能你应该只查找一个扩展精度的div算法并使用它。 Here's one,书中使用英特尔语法和16位操作。变量名称很清晰,并且有解释性文本,所以您应该可以重新实现它的32位。谷歌在这个词组中更多的点击,和/或看看libgcc的源代码。

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


如果您正在实施这是真的(高性能):

记住86的div指令做了64B/32B - > 32B师(但如果故障商溢出一个32位寄存器)。所以你可以检查你的高级双字的低位是否足够小,如果是这样的话,第一步只需要一个单位来得到高位数字。

只要您的号码小到可以用一个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)。


这可能会更快使用乘法逆做整个事情,即使这意味着做一个64×64B - 在32位机器上> 128B乘法。整数除法非常缓慢,只是流水线,但integer mul is very fast on Intel CPUs

AVX512-DQ adds a 64x64 -> 64b low multiply instruction,但那不能延长精度。 AVX512-IFMA增加了52bx52b低位和高位乘法指令,因此在几年之内,可能需要一个代码路径(在AVX512-IFMA硬件上运行的32位二进制代码),当您的编号的前64-52位是全零。

相关问题