14.3 工作原理

下面展示的是怎样用乘法来优化除法,其中借助了2^n的阶乘

14.3 工作原理 - 图1

M是一个magic系数

M的计算过程

14.3 工作原理 - 图2

因此这些代码片段通常具有这样的形式

14.3 工作原理 - 图3

n可以是任意数,可能是32(那么这样运算结果的高位部分从EX或者RDX寄存器中获取),可能是31(这种情况下乘法结果的高位部分结果右移)

n的选取是为了减少错误。

当进行有符号数除法运算,乘法结果的符号也会被放到输出结果中。

下面来看看不同之处。

  1. int f3_32_signed(int a)
  2. {
  3. return a/3;
  4. };
  5. unsigned int f3_32_unsigned(unsigned int a)
  6. {
  7. return a/3;
  8. };

在无符号版本的函数中,magic系数是0xAAAAAAAB,乘法结果被2^3*3除。

在有符号版本的函数中,magic系数是0x55555556,乘法结果被2^32除。

符号来自于乘法结果:高32位的结果右移31位(将符号位放在EAX中最不重要的位置)。如果最后结果为负,则会设置为1。

清单14.4:MSVC 2012/OX

  1. _f3_32_unsigned PROC
  2. mov eax, -1431655765 ; aaaaaaabH
  3. mul DWORD PTR _a$[esp-4] ; unsigned multiply
  4. shr edx, 1
  5. mov eax, edx
  6. ret 0
  7. _f3_32_unsigned ENDP
  8. _f3_32_signed PROC
  9. mov eax, 1431655766 ; 55555556H
  10. imul DWORD PTR _a$[esp-4] ; signed multiply
  11. mov eax, edx
  12. shr eax, 31 ; 0000001fH
  13. add eax, edx ; add 1 if sign is negative
  14. ret 0
  15. _f3_32_signed ENDP