【发布时间】:2015-08-27 16:52:26
【问题描述】:
查看编译器生成的 x86 程序集,我注意到(无符号)整数除法有时被实现为整数乘法。这些优化似乎遵循形式
value / n => (value * ((0xFFFFFFFF / n) + 1)) / 0x100000000
例如,除以 9:
12345678 / 9 = (12345678 * 0x1C71C71D) / 0x100000000
除以 3 将使用与 0x55555555 + 1 的乘法,等等。
利用mul 指令将结果的高位部分存储在edx 寄存器中这一事实,可以使用一个魔术值的单次乘法获得除法的最终结果。 (虽然这种优化有时会与最后的按位移位结合使用。)
我想了解一下这实际上是如何工作的。这种方法何时有效?为什么我们的“幻数”必须加 1?
【问题讨论】:
-
乘以的常数是倒数的近似值。随机的 +/- 1 在这里和那里是为了确保它总是正确地“四舍五入”。可以通过数学方法或通过对所有分子的强力测试来证明特定方法的正确性。 (对于 32 位,这是完全可行的。)
-
@Mysticial:这看起来像是对我的回答。
-
@ScottHunter 也许稍后我下班的时候。我没有足够的工具来给出全面的答案。
-
@Mysticial:你写的评论看起来比我见过的很多答案(还有一些我写的)要好。但我想这就是一个人获得 200K+ 代表的方式。
标签: assembly optimization bit-manipulation division multiplication