逆向课程第五讲逆向中的优化方式,除法原理,以及除法优化下

一丶除法的优化

1.有符号被除数无符号除数的情况下

高级代码为:

汇编中优化的体现形式

相比于昨天,我们发现了的 无符号 / 常量多出了点东西

无符号/常量

 

如果无符号/常量,那么我们还原的时候

套用公式即可

am >> n

a是被除数  m是设  2n/c   等价于  m == 2n/c

无符号的情况的,n的值是2^33次方  ,n = 33

根据上面得知,  m = 0AAAAAAABh

此时求出C来即可,  C = 除数

公式:

         2n / m = c

套进去得到

2^33次方 / 0AAAAAAABh = 被除数  结果向上取整

向上取整,结果就是3,那么得出被除数是3了.

2^33次方,也就是n怎么得出来的,依据上面的汇编代码n值等于1

也就是shr edx,1  那么我们知道,算一个除法的时候,必须扩展符号位

也就是 变成了 EDX.EAX 了,现在EDX右移一位,那么相当于 eax移动了32位+1,也就是33位,所以可以直接省略了.

所以此时EDX >> 1则是 33

此时继续,有符号 / 常量

 

看汇编代码,下边多了几条语句 显然与上面不同

此时还原的方法

n得出结果就是32,为什么?

因为edx直接使用了,我不用移位了.

下方的移动31位,是固定的,这个主要是解决有符号和无符号相除.

在这里,需要进行大量的数学公式推算,鉴于大家对数学不太明白,所以不再讲解.

我们只需要知道,当一个有符号 / 一个常量的时候,那么下方如果调整了.不用看.因为m的值如果按照 imul来计算的时候是一个负数.但是此时我们不能让它变为负数,所以最后进行符号位调整.

还原手法同上.

如果数学公式推导:

我们知道.

a/c的结果可以变为 

m = 2n / c

此时我们要知道,C的结果不会是整数的,所以使用的公式 是上整+1

也可能是小数,也需要上整+1

那么现在我们可以把符号位提取出来,这样也就是 移动31位(所以说是在32位系统下是固定死的),这样如果是负数,那么负数+1即可.如果是正数,那么是加0,还原的时候只看上三句即可.

2.无符号 / 7 和有符号/7的新的优化方式(当然可能不光是7介绍的是这种优化方式)

无符号/7的新方式.

 

又晕了是不是,一个DIV没用到,很难看到这是一个除法对不对.

先说下还原的公式,以及方法(至于公式怎么的出来的,那么可以看下方推导,当然这属于大数问题,可以不看.不过看了有好处)

 

2n / (M + 2^32)  = C(除数)即可.(别忘了结果向上取整)

n = 32(本身32起步,看系统,当然n的取值明天会讲) + 1 + 2 (指数相加) 结果为2 ^ 35次方

那么 2^35次方 / (M + 2^32) 结果救赎除数

那么我们按照数学界的公式去推一下.

推导:

首先得出:

 

得出最后的公式.

那么根据上面的程式,继而得到了

 一步一步简化

第一次简化: 可以把2^32次方拿到上面来

 第二次简化

第三次简化:

第四次简化

第五次简化

第六次简化:

第七次简化:

得出了

那么根据以前的除法公式

 m 

 

那么

 

进而简化为公式得出  一个大的M, M的值太大了.变为了一个大数问题,所以我们最终的M要加上1,或者加上2^32次方.(因为进位了)

那么

C =  (2^32 + 指数 + 指数) / (2^32 + M)  故而得出了C

简化为了

C = 2^n / M (别忘了M是一个大数)

有符号/7

这个和昨天一样,套用 C = 2^n / M 即可 (M是正常的,不是大数)

在这里讲解一下汇编代码:

请问为什么要 add一下.

这里我们就涉及到了有符号和无符号混乘的问题.

比如16位的年代,两个寄存器相乘,怎么解决溢出问题了.

A * 8086

A + ~A = FFFF

A + ~A + 1 = 10000 (求补码)

 

A * -(10000h - 8086h)

去掉负号

A * (8086h - 10000h )

那么得出

8086h - 10000h = dx.ax

又因为你减掉了补码 10000h

那么 

dx.ax + 10000h = 8086h

那么此时 10000h的高位变成了1,那么 dx直接加1即可了.

所以这就是为什么 add edx,ecx(乘积的高位)

到此,除数为正数的几种情况讲解完毕.

 

 

二丶除数为负数

1.除数为  -2的幂的情况下

高级代码:

汇编代码:

 公式还是一样的,向上取整的公式.也就是昨天的

b- 1是3

b是除数, 结果是2 ^2次方.

得出除数是4 只需要求反即可.

2.除数为-7的时候,有符号除,和无符号除的表现形式

2.1 有符号除

 高级代码还是上面的,只不过 -4 变为-7

argc / -7

此时,和 有符号 * 无符号问题又冲突了

A * 8086

只不过,现在的M变为负数了 需要你求补码了. 而又因为M是一个大数,下面需要调整1F(31)位,所以

还原公式为

2^n / neg(2^32 + M) = C  (向上取整)

也就是说依照上图,我们的M变为了16DB6DB6D了,此时要对它取反+1变为真正的M 然后用2^n次方去除,然后求出C来(除数)

计算一下得到

2^34 / neg(16DB6DB6D) = 6.99999xxxx 向上取整是7

那么此时怎么判断是否是  ±7那?

可以看汇编代码,里面有个 sub edx,ecx(相当于上面举例子 A * 8086,  那么此时 EDX只能减去乘积的高位才会得出真正的8086)

那么此时,我们判定了m的高位是负数,是求补后的,那么得出了  M是负数,说明了除数为负数,又因为还原了,M 得出的结果是原除数的绝对值.所以判定为负数.

 

2.2无符号/-7的优化.

 

这个是特殊还原公式

还原公式:

C = 2^n / M   转为16进制当做有符号解释即可.

现在的n是29  加上原来的32 = 61 那么就是2^61次方 / 20000001h  结果转化为16进制当做有符号解释.

 

 

转载于:

作者:IBinary
出处:http://www.cnblogs.com/iBinary/

 

posted @ 2019-07-20 23:20  gd_沐辰  阅读(414)  评论(0编辑  收藏  举报