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

关于MIPS三操作数divu指令及取余逻辑的技术咨询

MIPS汇编代码解析:divu指令与取模逻辑

原始代码对照

C代码

i = low + (1664525*(unsigned)high + 22695477*(unsigned)low) % (high-low+1);

MIPS汇编代码

lw      $3,40($fp)
li      $2,1638400              # 0x190000
ori     $2,$2,0x660d
mult    $3,$2
mflo    $2
lw      $4,36($fp)
li      $3,22675456       # 0x15a0000
ori     $3,$3,0x4e35
mult    $4,$3
mflo    $3
addu    $2,$2,$3
lw      $4,40($fp)
lw      $3,36($fp)
nop
subu    $3,$4,$3
addiu   $3,$3,1
divu    $0,$2,$3
bne     $3,$0,1f
nop
break   7
mfhi    $2
move    $3,$2
lw      $2,36($fp)
nop
addu    $2,$3,$2
sw      $2,8($fp)

已知:low存储在36($fp),high存储在40($fp)


核心疑问解答

1. 为什么divu是三操作数形式?

MIPS原生的divu指令确实是双操作数格式,但这里的三操作数写法是汇编器提供的语法糖,等价于:

  1. 将$2的值加载到LO寄存器
  2. 把HI寄存器置0
  3. 执行双操作数divu $0, $3(即把HI:LO组成的64位无符号数除以$3)

这种写法简化了操作,无需手动设置HI和LO寄存器,直接指定32位被除数和除数即可完成无符号除法。

2. 为什么用mfhi取结果而非mflo?

原C代码中需要计算的是无符号取模运算(%),而MIPS的divu指令执行后:

  • 除法的商会被存入LO寄存器,用mflo读取
  • 除法的余数会被存入HI寄存器,用mfhi读取

这里要获取的是取模结果,也就是余数,因此必须用mfhi而非mflo。


完整代码工作机制解析

  1. 计算1664525*high

    • 从40($fp)取出high到$3
    • 通过li+ori组合出系数1664525(0x19660d)存入$2
    • 执行mult $3,$2完成乘法,用mflo $2取出乘积的低32位(无符号场景下足够)
  2. 计算22695477*low

    • 从36($fp)取出low到$4
    • 通过li+ori组合出系数22695477(0x15a4e35)存入$3
    • 执行mult $4,$3完成乘法,用mflo $3取出乘积的低32位
  3. 求和得到被除数

    • addu $2,$2,$3:将两个乘积相加,结果1664525*high + 22695477*low存入$2
  4. 计算除数high-low+1

    • 重新取出high和low,执行subu $3,$4,$3得到high-low
    • addiu $3,$3,1完成+1,除数存入$3
  5. 无符号除法与除数检查

    • divu $0,$2,$3:执行无符号除法,被除数为$2,除数为$3
    • bne $3,$0,1f:如果除数不为0,跳过中断指令;否则执行break 7触发除数为0的异常
  6. 计算最终结果i

    • mfhi $2:取出取模运算的余数
    • addu $2,$3,$2:将余数与low相加,得到i的值
    • sw $2,8($fp):将结果存入指定内存位置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:50:25