《C++反汇编与逆向分析技术揭秘》——观察各种表达式的求值过程
---恢复内容开始---
- 加法:
示例:


常量相加,则在编译期间就计算出两个常量相加后的结果,直接将这个结果参与运算,减少了运行期的计算。当有变量参与运算时,会先取出内存中的数据,放入通用寄存器中,再通过加法指令来完成计算过程得到结果。
如果开启O2选项,则是考虑效率优先,编译出来的汇编代码会有很大的变化:

如果使用Release版本开启O2选项后,再查看反汇编,则略过很多无用的步骤,直接给printf压入一个常量作为参数:

如果我们稍加修改:

用命令行参数的个数argc去初始化两个变量,那么由于argc的个数在编译期间无法确定,所以程序中的变量就不会被常量替换掉:

- 乘法
乘法运算对应的汇编指令有有符号imul和mul两种。由于乘法指令的执行周期较长,在编译过程中,编译器会先尝试将乘法转换成加法,或使用移位等周期较短的指令。当它们都不可转换时,才会使用乘法指令。


这里Debug版本的代码,更侧重调试,如果这个乘数常量不是2的幂,那么就会使用imul指令进行乘法。当常量值为2的幂时,编译器会采用执行周期短的左移运算来代替执行周期长的乘法指令。当乘数和被乘数同时都是未知变量时,则无法套用优化方案。这时编译器不会优化处理,将直接使用乘法指令完成计算。

乘法运算与加法运算相结合采用LEA指令来处理。

Release版本优化后:
乘以15变成乘以16再减去自身:



两个未知变量相乘,无法优化,依然使用imul指令:

- 除法
除法运算对应的汇编指令分为有符号idiv和无符号div

先用cdq命令扩展高位,然后直接使用idiv有符号除法和无符号div去进行计算。除法运算的计算周期较长,效率也较低,所以编译器想尽办法用其它运算指令代替除法指令:

除以2采用的是右移。在扩充完高位之后,要自身减去扩充位,然后再右移一位:

除以非2的幂的常量:

余数保存在edx中:

切换到Release版本,各类型的除法会进行一定的优化,比如除以非2的幂的时候:

这里是除数为负的2的幂的情况:

除数为负的非2的幂的情况:

- 自增

- 表达式短路
逻辑与运算:


逻辑或运算,等于1直接满足条件return:

- 条件表达式
示例:


- 位移运算
对于有符号位移:

有符号数右移使用sar指令,保留符号位:

对于无符号位移:

使用shr指令,右移高位补0:

有符号数和无符号数的左移都是一样的。
---恢复内容结束---
《C++反汇编与逆向分析技术揭秘》——观察各种表达式的求值过程的更多相关文章
- C++反汇编与逆向分析技术揭秘
C++反汇编-继承和多重继承 学无止尽,积土成山,积水成渊-<C++反汇编与逆向分析技术揭秘> 读书笔记 一.单类继承 在父类中声明为私有的成员,子类对象无法直接访问,但是在子类对象的 ...
- 《C++反汇编与逆向分析技术揭秘》--算术运算和赋值
一.加法 1.Debug下: 14: int nVarOne0 = 1 + 5 - 3 * 6;//编译时计算得到结果 00C0550E C7 45 F8 F4 FF FF FF mov dword ...
- 《C++反汇编与逆向分析技术揭秘》--认识启动函数,找到用户入口
<C++反汇编与逆向分析>和<程序员的自我修养>都是以VC6的代码作为例子讲解的.这里是在vs2017下,CRT代码有些区别,但整体流程上都是初始化环境,设置参数,最后转到用户 ...
- 《C++反汇编与逆向分析技术揭秘》——基本数据类型的表现形式
---恢复内容开始--- 基本的浮点数指令 示例代码: Visual Studio 2013的反汇编代码是: 对于movss,表示移动标量单精度浮点值 将标量单精度浮点值从源操作数(第二个操作数)移到 ...
- 《C++反汇编与逆向分析技术揭秘》之十——构造函数
对象生成时会自动调用构造函数.只要找到了定义对象的地方,就找到了构造函数调用的时机.不同作用域的对象的生命周期不同,如局部对象.全局对象.静态对象等的生命周期各不相同,只要知道了对象的生命周期,便可以 ...
- 《C++反汇编与逆向分析技术揭秘》——函数的工作原理
各种调用方式的考察 示例: cdecl方式是调用者清空堆栈: 如果执行的是fastcall: 借助两个寄存器传递参数: 参数1和2借助局部变量来存储: 返回值 如果返回值是结构体: 返回值存放在eax ...
- 《C++反汇编与逆向分析技术揭秘》——流程控制语句的识别
if...else...语句 示例: if构成多分支语句 switch 有序线性的switch: 3E82D8位置存放了一个表,标明了要跳转到的地址: 这里的每四字节都标明的是每个case块的首地址: ...
- 《C++反汇编与逆向分析技术揭秘》之12——继承
识别类和类之间的关系 在父类中声明为私有的成员,虽然子类对象无法直接访问,但是在子类对象的内存结构中,父类私有的成员数据依然存在. 在没有提供构造函数的时候,系统会尝试提供默认的构造函数: 当子类中没 ...
- 《C++反汇编与逆向分析技术揭秘》之11——虚函数
虚函数的机制 当类中定义有虚函数时,编译器会将该类中所有虚函数的首地址保存在一张地址表中,这张表被称为虚函数地址表.编译器还会在类中添加一个虚表指针. 举例: CVirtual类的构造函数中没有进行任 ...
随机推荐
- MVC 4 插件化架构简单实现
转ASP.NET MVC 4 插件化架构简单实现-思路篇 用过和做过插件的都会了解插件的好处,园子里也有很多和讨论,但大都只些简单的加载程序集什么的,这里主要讨论的就是使用 ASP.NET MVC ...
- 寻找最大的k个数
这个题目是非常经典的一个题目,解法也有很多,现在就把我已经理解的解法记录下来. 题目描述 有n个无序的数,它们各不相等,怎样选出其中的最大的k个数呢? 题目分析: 解法1: 最容易想到的就是把n个数进 ...
- poj2236无线网络
这一题的大意:在救灾当中需要用网络,这堆人就用笔记本建了一个无线网,但是来,互相通信都是有距离限制的,一台电脑只能和距离他为d的电脑通信,然后一台电脑也可以通过几台电脑搭成线这样通信.然后就是输入每台 ...
- MongoDB学习(翻译3)
支持的where字句(比较多,今天先写一部分) 本节介绍支持的where字句 正如前面提到的,不是所有的C#表达式都支持where子句.您可以以此文为指导,或者你可以尝试表达,看看它是否工作(如果不支 ...
- 简单使用JSON,通过JSON 字符串来创建对象(二)
把 JSON 文本转换为 JavaScript 对象 JSON 最常见的用法之一,是从 web 服务器上读取 JSON 数据(作为文件或作为 HttpRequest),将 JSON 数据转换为 Jav ...
- S2SH整合
Struts2.Spring.Hibernate三大框架在一个项目中的具体职责分配如下: 三大框架整合,导入各个框架和整合所需的包(本项目采用的是Struts2.3+spring3.0+hiberna ...
- Reeder Web版
Reeder Web版 访Reeder界面效果 一直很欣赏触控手势的代码实现,所以最近折腾了个Javascript触控手势库--JTouch,效果还有诸多不完善之处,苦于硬件设备不完善,针对ie10的 ...
- CDM业务单据,表体单价列赋值所需要注意的问题
需要将销售退回入库单据的单价自动去商品资料里的零售价值. 写了检索方案,然后 select * ............. spkfk.lshj as dj......... ,但是发现定价依 ...
- MacOSX中使用NSWindow创建背景透明的窗体
1.Windows 在window上创建异形窗体必须要使用WS_EX_LAYERED样式,再调用SetLayeredWindowAttributes设置透明度或者透明颜色属性.用updatelayer ...
- JBPM之JPdl小叙
JPdl:jbpm流程定义文件,下面是一个简单的流程定义文件: <?xml version="1.0" encoding="UTF-8"?> < ...