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

汇编语言中如何通过移位操作实现非2的幂次整数除法

汇编中用移位组合实现常数除法的方法

当然有和乘法对应的移位类指令组合实现除法的方案,早年没有硬件除法指令的架构(比如经典ARMv4/ARMv5)全靠这套方案做整数除法,性能比软件逐位模拟除法快得多。

不过除法的实现逻辑比乘法稍复杂:你之前用的乘3实现,本质是把乘数拆成2的整数次幂的和(3=2+1),所以拆成移位+加法就能做。但除数如果不是2的整数次幂,它的二进制倒数是无限循环小数,没法拆成有限个2的负整数次幂的和,所以没法像乘3那样用两三条指令搞定全范围的精确计算。

实际工程里通用的方案是定点倒数乘法:除以常数N等价于乘以N的定点放大版倒数,最后做移位修正,过程只需要少量乘法、移位、加减指令,不需要调用除法指令。

举个例子:32位无符号数除以3(对应你说的9/3场景)

编译器生成的标准实现用的是0x55555556作为魔数——这个值是1/3放大2^33倍后的定点整数,代码如下:

; 输入:r0 = 待计算的无符号整数,比如示例中的9
; 输出:r0 = r0 / 3 的无符号商
ldr r1, =0x55555556   ; 加载1/3的33位定点倒数
umull r2, r1, r0, r1  ; 做无符号32位乘法,结果高32位存r1,低32位存r2
mov r0, r1, lsr #1    ; 高32位逻辑右移1位,得到最终商

代入r0=9计算:9和0x55555556相乘的高32位值是6,右移1位刚好得到3,结果完全正确。

如果你的场景要求完全不用乘法指令、且待计算的数值范围很小(比如0~100),也可以用多次移位+加法逐次逼近1/3的值,本质是把无限循环的二进制倒数截断到需要的精度,不过这种方案代码更长,适用范围窄,实际很少用。

几个注意点

  • 你之前了解的用LSR实现除2,本质是这套方案的特例:除以2的倒数是0.5,放大2^1倍就是1,乘完右移1位刚好对应单条LSR指令。
  • 这套方案仅对除数为常数的场景性价比最高,如果除数是运行时可变的变量,还是需要用通用除法逻辑。
  • 如果处理的是有符号数,对应的魔数、移位偏移、舍入修正逻辑都要调整,避免负数计算出错。
  • 日常写汇编不用自己手算魔数,开启优化的编译器会自动把常数除法替换成最高效的移位+加减+短乘法组合,不需要手动写DIV指令。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:54:24