《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类的构造函数中没有进行任 ...
随机推荐
- 随机函数Surprising
之前写了个用来抽取1-54号的随机函数,发现30-40出现的情况很大,就在果壳上提问了一下//听取了某个大神的建议循环了10000次之后惊喜的发现这样写出现了一大堆相同的数字! 之后有个很神大牛解答了 ...
- 基本功能的shell
手把手教你编写一个具有基本功能的shell(已开源) 刚接触Linux时,对shell总有种神秘感:在对shell的工作原理有所了解之后,便尝试着动手写一个shell.下面是一个从最简单的情况开始,一 ...
- MongoDB:利用官方驱动改装为EF代码风格的MongoDB.Repository框架 二
本次改动的主要内容是实现MongoDB.Repository对MongoDBRef的支持. MongoDB对一对一,一对多,多对多关系的维护,官方推荐文档嵌入方式,反映到模型的设计如下: public ...
- OpenStack调研
OpenStack调研:OpenStack是什么.版本演变.组件关系(Havana).同类产品及个人感想 一点调研资料,比较浅,只是觉得部分内容比较有用,记在这里: 首先,关于云计算,要理解什么是SA ...
- Object-c学习之路(oc点语法)
最近想学习object-c了自己上网找了一些资料自学了一下:oc中的点语法是为了java.c等的程序员更好的上手而添加的功能. 主函数 // // main.m // OcTest1 // // Cr ...
- ASP.NET MVC页面UI之联动下拉选择控件(省、市、县联动选择)
地区选择操作在WEB应用中比较常见的操作,本文在.net mvc3下实现了省市县三级联动选择功能. 本文博客出处:http://www.kwstu.com/ArticleView/admin_2013 ...
- HashMap源码剖析
HashMap源码剖析 无论是在平时的练习还是项目当中,HashMap用的是非常的广,真可谓无处不在.平时用的时候只知道HashMap是用来存储键值对的,却不知道它的底层是如何实现的. 一.HashM ...
- C# BackgroundWorker详解,图例,原理分析
先声明,大部分资料均参考网上,进行了整理. 1. 在 VS 中添加了 BackgroundWorker 组件, 该组件在多线程编程方面使用起来非常 方便,然而在开始时由于没有搞清楚它的使用机制, 走了 ...
- 统计知识选讲(二)——主成分分析(PCA)的推导和应用
1.数学推导 根据上讲的思想,我们可以用下图来进行数学上的推导. 2.PCA的步骤 1)对原始数据进行标准化处理:对该指标变量进行标准化, 2)计算相关系数矩阵(协方差矩阵) 3)计算相关系数矩阵的特 ...
- jsp传值乱码解决办法
在jsp中,我们经常从数据库读取数据返回客户端,但我们常常在制作时出现乱码现象,所以我们可以用<%request.setCharacterEncoding("UTF-8"); ...