You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何idiv指令在RDX中生成的带符号除法余数结果不正确?

为什么idiv计算-1 mod 20得到15而非预期的19?

你碰到的问题本质上有两个关键点:一是带符号除法中rdx的初始化方式错误,二是x86的idiv指令返回的余数规则和你预期的数学模运算规则有差异。

1. 错误的直接原因:rdx初始化错了

x86-64的idiv指令是把**128位的带符号数rdx:rax**当成被除数,除以你指定的源操作数(这里就是rbx里的20)。当你要计算64位带符号数-1除以20时,必须先把rax里的-1符号扩展到rdx,形成完整的128位被除数。

你用mov rdx, 0初始化rdx,相当于把被除数变成了0x0000000000000000FFFFFFFFFFFFFFFF——也就是十进制的4294967295,一个正数。用这个正数除以20:

  • 商是 4294967295 ÷ 20 = 214748364
  • 余数是 4294967295 - (20 × 214748364) = 15
    这就是你在GDB里看到RBX=15的根本原因。

正确的初始化方式是用cqo指令,它会自动把rax里的64位带符号数符号扩展到rdx,比如rax=-1时,rdx会被设为0xffffffffffffffff(和rax的符号一致,都是-1的补码):

mov rax, -1
cqo         ; 执行后rdx和rax都是-1的补码
mov rbx, 20
idiv rbx

2. 为什么正确初始化后还要调整余数?

就算你用cqo正确初始化了rdx,执行idiv后得到的余数也会是-1,而不是你想要的19——这是因为x86的idiv遵循两个规则:

  • 余数的符号必须和被除数一致
  • 商是向零取整的

对于-1 ÷ 20来说,向零取整的商是0,所以余数就是 -1 - (20 × 0) = -1。但数学上的模运算(-1 mod 20)要求结果是非负数,这时候你需要对余数做个小调整:如果余数是负数,就加上除数(因为除数是正数),就能得到正的模结果了:

mov rax, -1
mov rbx, 20
cqo
idiv rbx
test rdx, rdx   ; 检查余数是否为负
jns store_result ; 余数非负的话直接保存
add rdx, rbx    ; 余数为负就加上除数转成正数
store_result:
mov rbx, rdx    ; 此时RBX的值就是19,符合你的预期

内容的提问来源于stack exchange,提问作者hossein ahmadi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 14:03:12