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

kx1ctssn  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(67)

假设您想使用gas将-198077031546722079779除以23。由于这个被除数大于%rax,如何将其放入%rdx:%rax中?我读的所有关于汇编的书都避免用例子来说明idiv,所以我迷失了方向。

fcwjkofz

fcwjkofz1#

您将高位放入rdx,将低位放入rax,您可能知道。
如果你想在程序中使用这个数字作为常量,那么是的,十六进制是一种可能的方法来分割它。我使用calc进行转换,加上2^128表示为无符号二进制补码,然后使用printf("%x")将其打印为十六进制。结果是0xfffffffffffffff543210543edc9abdd。所以我们可以

movq $0xfffffffffffffff5, %rdx
movq $0x43210543edc9abdd, %rax

字符串
如果你能让气体为你做算术就好了。它确实支持任意精度的常量(“bignums”),但不幸的是不允许在立即数中使用它们。它也不能用它们做任何算术,正如Jester发现的那样(根据下面的评论)。
但是,它支持使用.octa指令将128位整数数据组装到内存中。所以你可以

.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
# ...


请注意,我们使用的是RIP相对寻址。如果你在一个不合适的情况下,那么就用movq number, %rax ; movq number+8, %rdx
如果您在运行时接收数字作为输入,那么您需要实现十进制到二进制转换例程(如strtol),但它使用128位算术。所以加法需要一个add/adc对,乘法需要几个“手写”式的乘法指令,等等。

相关问题