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

一丶除法的优化

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/

原文地址:https://www.cnblogs.com/gd-luojialin/p/11219757.html

时间: 2024-10-12 13:00:37

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

逆向课程第三讲逆向中的优化方式,以及加减乘

逆向课程第三讲逆向中的优化方式,以及加减乘 一丶为什么要熟悉优化方式 熟悉优化方式,可以在看高级代码的时候浮现出汇编代码,以及做逆向对抗的时候,了解汇编代码混淆 优化和混淆是相反的 优化: 指的是汇编代码越少越好,让程序更快的执行 混淆: 一条汇编代码变为多条汇编代码,影响逆向人员的破解能力,但是软件的效率大大降低 二丶加减乘的常见的几种优化方式 优化方式分为: 1.常量折叠 2.常量传播 3.变量去除 这些优化方式成为窥孔优化 (有10几种后面会一一到来) 首先了解什么是常量折叠,常量传播,然

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

一丶为什么要熟悉除法的优化,以及除法原理 是这样的,在计算机中,除法运算对应的汇编指令分为 DIV(无符号除法指令) 以及 IDIV(有符号除法指令). 但是,除法指令的执行周期较长效率很低.所以编译器想进办法的用其它指令去代替除法指令. 比如: DIV 指令是100个周期 计算 2 / 2 那么可能在汇编中的表现形式是这样的 CDQ  符号扩展 DIV EDX,2 好,现在100个周期没有了 减法和加法指令,指令周期是4个那么上面的公式可以演化为 mov eax,2 sub eax,2 就算m

FineReport中以jws方式调用WebService数据源方案

在使用WebService作为项目的数据源时,希望报表中也是直接调用这个WebService数据源,而不是定义数据连接调用对应的数据库表,这样要怎么实现呢? 在程序中访问WebService应用服务,将WebService返回的数据转为程序数据集,然后在设计器中调用. 以axis1.4上的WebService为例,介绍其取数方式以及将数据转换为WebService的程序数据集的过程. WebService应用服务 如在Tomcat下的Axis工程中以jwa方式发布了一个WebService应用服

C# 中参数验证方式的演变

一般在写方法的时候,第一步就是进行参数验证,这也体现了编码者的细心和缜密,但是在很多时候这个过程很枯燥和乏味,比如在拿到一个API设计文档的时候,通常会规定类型参数是否允许为空,如果是字符可能有长度限制,如果是整数可能需要判断范围,如果是一些特殊的类型比如电话号码,邮件地址等,可能需要使用正则表达式进行判断. 通常,我们一般都是在方法开始的地方进行条件判断,然后抛出合适的异常,这是最普通和通用的做法,但是在.NET中,利用一些语言特性和类库,可以使用一些其他的方式将我们从复杂繁琐的工作中解放出来

32位汇编第五讲,逆向实战干货,(OD)快速定位扫雷内存.

32位第五讲,逆向实战干货,快速定位扫雷内存. 首先,在逆向之前,大家先对OD有一个认识. 一丶OD的使用 标号1: 反汇编窗口 (显示代码的地址,二进制指令,汇编代码,注释) 标号2: 寄存器窗口(显示通用寄存器,段寄存器,以及浮点协处理器,32位中还有多媒体寄存器) 标号3: 信息窗口 (这个主要是显示当你运行到的程序的位置处的信息) 标号4: 数据窗口   (内存中的数据,可以在这里查看内存) 标号5:堆栈窗口 (查看栈中的内容,以及变量的内容) 标号6,标号7,标号8 ,属于工具窗口,不

逆向知识十三讲,汇编中数组的表现形式,以及还原数组

逆向知识十三讲,汇编中数组的表现形式,以及还原数组 讲解数组之前,要了解数组的特性 1.数据具有连续性 2.数据类型相同 比如: int Ary[3] = {0,1,2}; 我们可以看出,上面定义的数组,数据是连续的,其中每个数据类型大小都是int类型(类型也是一样的) 汇编中识别数组: 1.地址连续 2.带有比例因子寻址   (lea  reg32,[xxx  + 4 *xxxx]) 一丶一维数组在汇编中的表现形式 首先说下数组寻址公式,便于下面讲解 公式: 数组首地址 + sizeof(ty

逆向知识第九讲,switch case语句在汇编中表达的方式

一丶Switch Case语句在汇编中的第一种表达方式 (引导性跳转表) 第一种表达方式生成条件: case 个数偏少,那么汇编中将会生成引导性的跳转表,会做出 if else的情况(类似,但还是能分辨出来的) 1.高级代码: #include "stdafx.h" int main(int argc, char* argv[]) { switch(argc) { case 0: printf("case 0\n"); break; case 1: printf(&

逆向知识第八讲,if语句在汇编中表达的方式

一丶if else的最简单情况还原(无分支情况) 高级代码: #include "stdafx.h" int main(int argc, char* argv[]) { unsigned int nNumber = 0; scanf("%ud",&nNumber); if(argc == 0) { nNumber = 0; //第一种情况下无分支 } else { nNumber = -1; } return nNumber; } 总共两种情况,我们看下R

C++中字母大写和小写转换实现的优化

C++中字母大写和小写转换实现的优化 write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 在本文中所有以转换为小写为例. 从推荐复用代码的角度来看,用库函数是不错的办法: 方案一: char gc1[53] = "abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ"; void wayOne() { strlwr(gc1); } 长处是使用方便,别人看着也easy理解