前言
除法的指令周期比较长,用移位后乘法替代除法可以很有效的优化算法,本文用以小结,附有实例(都是release版本的实例以及自己画的图),希望在写作之余加深理解
整数的除法
(1)有符号除法,除数为2^n
数学公式为:如果x>=0,x/2^n=x>>n ; 如果x<0,x/2^ n=(x+(2^n-1))>>n
下面为x/4的例子:
以-4/4为例子:
ps:1.负数在编译器中以补码储存
2.负数取反符号位不变
3.edx=0xffffffff其实也就是-1
(2)有符号除法,除数为-2^n
同(1),区别在汇编代码在计算后用neg eax将结果取反,并没有先识别被除数的正负
(3)有符号除法,除数为正非2^n
优化公式1:x>=0,则x/o=x*c>>32/64>>n
如果x<0,则x/o=(x*c>>32/64>>n)+1
优化公式2:x>=0,则x/o=(x*c>>32/64)+x>>n
如果x<0,则x/o=(x*c>>32/64)+x>>n+1
下面是x/7的实例:
c为MAGIC_NUM , n为右移总次数
ps:优化公式括号内是优先计算的公式,之外按从左到右的顺序处理(+x>>n指先加x再右移n)
(下面这张解析图又是几天之后重新审视后做的笔记了,但优化公式2并未给以证明,因为当时直接代入实例时也无法得到正确解,感觉有冗余步骤,所以不予推导解析)
对于优化公式1的解析图,字不好看多多
(4)有符号除法,除数为负非2^n
优化公式1:x>=0,则x/o=x*c>>32/64>>n
如果x<0,则x/o=(x*c>>32/64>>n)+1
优化公式2:x>=0,则x/o=(x*c>>32/64)+x>>n
如果x<0,则x/o=(x*c>>32/64)+x>>n+1
(5)无符号除法,除数为2^n
用移位指令替代除法
(6)无符号除法,除数为非2^n的情况a
优化公式:x/o=x*c>>32/64>>n
(7)无符号除法,除数为非2^n的情况b
优化公式:x/o=(x-(x*c>>32/64)>>n1)+(x*c>>32/64)>>n2
总结
所有用移位和加减法运算替换除法指令的操作本质上都是用多个2^n数来替代被除数
隔两天更新汇编取余优化算法,一个人研究算法属实太占时间了@.@