|
edx 传递结果高位
ecx传递成员对象指针
除数是负数 2的整数次幂
int main(int argc, char* argv[])
{
printf("%d\r\n",argc / -4);
return 0;
}
反汇编代码
mov eax, [esp+argc]
cdq
and edx, 3
add eax, edx
sar eax, 2
neg eax ;结果比 argc / 4 多一条求补
分析: argc / -4 = -(argc / 4 ) 因此相对 argc / 4 求补就可以了
除数是负数且非 2的整数次幂
int main(int argc, char* argv[])
{
printf("%d\r\n",argc / -5);
return 0;
}
反汇编代码:
mov ecx, [esp+argc]
mov eax, 99999999h
imul ecx
sar edx, 1
mov eax, edx
shr eax, 1Fh
add edx, eax
分析: 上式用前面的方式还原代码是错的
2^33 / 99999999h = 4 ;明显是不对的
那该怎么还原呢?
前面知识我们可以知道 A/C => AM >> n M = 2^n/C
那么 A/ (-C) => -(AM) >> n => A * (-M) >> n M是常量 -M 编译器可以计算
所以: 上式 M 值是求补后的 值
那怎么判断呢?
我们看出 : M 是一个负数 ,按之前所学的知识,M为负数,那么需要 进行调整, 但是上式明显没有,所以可以判断除数为负 (M为负数 ,且乘法移位之间没有调整 即没有 add edx, ecx)
因此还原时需要先对M值进行求补 ,在计算出 C 的绝对值 ,再由于是负数 ,所以 再把结果 取负
还原: neg(99999999h) = - (99999999h) + 1 = 6666 6667h
C = 2^33 / 6666 6667h= 5
因为可知除数为负,所以除数为 -5
可以得到结论: 是除法定式 M为负数, 乘法之后没有调整 那么被除数是负数,M需要求补,求出C的绝对值
int main(int argc, char* argv[])
{
printf("%d\r\n",argc / -7);
return 0;
}
反汇编代码:
mov ecx, [esp+argc]
mov eax, 6DB6DB6Dh
imul ecx
sub edx, ecx
sar edx, 2
mov eax, edx
shr eax, 1Fh
add edx, eax
上面跟前面的比较,我们发现,代码出现了调整,且是减调整
定式: 是除法定式,M为正数,且乘法移位之前有减调整,可以确定除数为负
neg(6DB6DB6Dh) = - (6DB6DB6Dh) + 1 = 9249 2493h 2454267027
|C| = 2^34 / neg(6DB6DB6Dh)=2^34 / 2454267027 = 7
因为 C为负数 所以 C = -7
可以得到结论: 是除法定式 M为正数, 乘法之后有sub调整 那么被除数是负数,M需要求补,求出C的绝对值
除法有效性问题
用于确定除法误差的范围 ,即 确定 n 的值
由 推导 6 可知: M / C = q..r
0<= M /(2^n *C) < | 1/C| n值32起步,当不满时是 n 值+1 在计算,知道 n 上面不等式




除法总结
除法总结
- 调整方法:正数是加,负数是减。

(1)除数为变量
div / idiv ;无优化
(2)除数为常量
- 无符号除法:
-
- 除数为2的幂
-
-
- 公式:
c = 2^n
- 定式:
mov reg, A
shr reg , n ;直接移位
-
- 除数为非2的幂
-
-
- MagicNumber无进位:
-
-
-
- 公式**:**
c = 2^(n+32) / MagicNumber
- 定式:基于此原型有四种变化。
mov eax, MagicNumber
mul A
shr edx, n
-
-
- MagicNumber有进位:
-
-
-
- 公式**:**
c = 2^(1+n+32) / (MagicNumber + 2^32)
- 定式:
mul / sub / shr / add / shr
mov eax, MagicNumber
mul A
sub A, edx
shr A, 1
add A, edx
shr A, n
- 有符号除法 :
-
- 除数为正
-
-
- 除数为2的幂
-
-
-
-
- 公式:
c = 2^n
- 定式:
cdq / and / add / sar
mov eax, A
cdq
and edx, 2^n ‐ 1
add eax, edx
sar eax, n
-
-
- 除数为非2的幂
-
-
-
- MagicNumber为正数:
-
-
-
-
- 公式**:**
c = 2^(n+32) / MagicNumber
- 定式:
mov eax, MagicNumber
imul A
sar edx, n
;调整取整方向(序列不唯一)
mov reg, edx ; 或:mov eax, edx
shr reg, 31 ; 或:cdq
add reg, edx ; 或:sub eax, edx
-
-
-
- MagicNumber为负数:
-
-
-
-
- 公式**:**
c = 2^(n+32) / MagicNumber
- 定式:
mov eax, MagicNumber
imul A
add edx, A
sar edx, n
mov reg, edx
shr reg, 31
add edx, reg
-
- 除数为负
-
-
- 除数为2的幂
-
-
-
-
- 公式:
c = ‐(2^n)
- 定式:
cdq / and / add / sar / neg
mov eax, A
cdq
and edx, 2^n ‐ 1
add eax, edx
sar eax, n
neg eax
-
-
- 除数为非2的幂
-
-
-
- MagicNumber为正数:
-
-
-
-
- 公式**:**
c = ‐(2^(n+32) / (2^32 ‐ MagicNumber))
- 定式:
mov eax, MagicNumber
imul A
sub edx, A
sar edx, n
mov reg, edx
shr reg, 31
add edx, reg
-
-
-
- MagicNumber为负数:
-
-
-
-
- 公式**:**
c = ‐(2^(n+32) / neg(MagicNumber))
- 定式:
mov eax, MagicNumber
imul A
sar edx, n
mov reg, edx
shr reg, 31
add reg, edx ; ×add edx, reg |
|