64位Intel CPU执行idiv前是否需转有符号整数为十六进制?gas大被除数处理
x86-64下
idiv指令的常见问题解答 1. 执行idiv前需要把有符号整数转成十六进制吗?
完全不需要。CPU只认二进制机器码,你在汇编代码里用十进制、十六进制甚至八进制写数值都可以,汇编器(比如gas)会自动帮你转换成CPU能识别的二进制格式。写负数直接加负号就行,比如$-456,不用手动转成十六进制补码。
2. 超大有符号被除数怎么放进%rdx:%rax(gas环境)
当被除数超过64位(%rax的存储上限)时,要把它拆成低64位和高64位,分别放到%rax和%rdx里,而且必须保证%rdx:%rax是这个数的128位有符号补码形式——尤其是负数,%rdx得是%rax的符号扩展结果(简单说就是%rax最高位是1的话,%rdx全填1;是0的话全填0)。
拿你说的-198077031546722079779举例,具体操作如下:
- 先算出这个数的128位补码拆分结果:低64位是
0xD49E4B29806A5734,高64位是0xFFFFFFFFFFFFFFFD - 用gas的
movabsq指令加载64位立即数到寄存器,然后执行除法:
.text .globl _start _start: # 加载被除数低64位到%rax movabsq $0xD49E4B29806A5734, %rax # 加载被除数高64位到%rdx movabsq $0xFFFFFFFFFFFFFFFD, %rdx # 除数23放到%rbx(idiv不支持直接用立即数当除数) movq $23, %rbx # 执行有符号除法:%rdx:%rax ÷ %rbx,商存%rax,余数存%rdx idivq %rbx # 示例:把商作为退出码(实际退出码只取低8位) movq %rax, %rdi movq $60, %rax syscall
- 要是不想手动算十六进制,也可以把数值存在数据段再加载:
.data # 128位被除数,低64位在前,高64位在后(小端存储规则) big_dividend: .quad 0xD49E4B29806A5734, 0xFFFFFFFFFFFFFFFD .text .globl _start _start: movq big_dividend, %rax # 读低64位 movq big_dividend+8, %rdx # 读高64位 movq $23, %rbx idivq %rbx # 后续处理商或余数...
重要提醒:
idiv r/m64要求%rdx:%rax是完整的128位有符号数,负数的高64位必须是符号扩展后的结果,不能随便填。idiv不支持立即数除数,必须把除数放进寄存器或者内存里。
内容的提问来源于stack exchange,提问作者ntos
相关产品推荐
相关产品推荐

