在 64 位 Intel CPU 中执行“idiv”之前,是否将有符号整数转换为十六进制?

nto*_*tos 2 assembly x86-64 integer-division

假设您想使用Gas将 -198077031546722079779 除以 23 。由于这个股息比较大%rax,你怎么投入呢 %rdx:%rax?我读过的所有关于汇编的书都避免idiv用例子来说明,所以我迷失了。

Nat*_*dge 6

您可能知道,您将高位放入,rdx将低位放入。rax

如果您尝试在程序中使用该数字作为常量,那么是的,十六进制是一种可能的拆分方法。我使用calc对其进行转换,添加 2^128 将其表示为无符号二进制补码数,然后使用printf("%x")将其打印为十六进制。结果是0xfffffffffffffff543210543edc9abdd。所以我们可以做

movq $0xfffffffffffffff5, %rdx
movq $0x43210543edc9abdd, %rax
Run Code Online (Sandbox Code Playgroud)

如果你能让gas帮你算算那就太好了。它确实支持任意精度常量(“bignums”),但不幸的是不允许您在立即数中使用它们。正如 Jester 发现的那样(根据下面的评论),它也不能对它们进行任何算术运算。

但是,它确实支持使用指令将 128 位整数数据组装到内存中.octa。所以你可以做

        .section .rodata
number:
        .octa -198077031546722079779
# ...
movq number(%rip), %rax # x86 is little endian, least significant qword is at lower address
movq (number+8)(%rip), %rdx
# ...
Run Code Online (Sandbox Code Playgroud)

请注意,我们使用的是 RIP 相对寻址。如果您处于不合适的情况,那么就这样做movq number, %rax ; movq number+8, %rdx

如果您在运行时接收数字作为输入,那么您需要实现一个十进制到二进制的转换例程(如strtol),但它使用 128 位算术。因此,加法需要一add/adc对,乘法需要几个“普通”风格的乘法指令,等等。

  • 它支持 bignum 常量,但我认为它根本不支持任何算术,甚至不支持“.octa”。我的版本当然甚至不能加 1,抱怨_“左操作数是一个大数;假定整数 0”_ (3认同)