《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类的构造函数中没有进行任 ...
随机推荐
- 静态页面调试JS出现跨域问题
在chrome浏览器或者firefox浏览器里,由于安全限制的原因,本地调试JS,如果不配服务器环境而直接打开页面,那所有的AJAX操作会抛出下面错误: XMLHttpRequest cannot l ...
- HTTP报文格式详解
HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的.HTTP有两类报文:请求报文和响应报文. HTTP请求报文 一个HTTP请求报文由请求行(request ...
- 使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑
翻译:使用 ASP.NET MVC 4, EF, Knockoutjs and Bootstrap 设计和开发站点 - 6 - 业务逻辑 Part 3: 设计逻辑层:核心开发 如前所述,我们的解决方案 ...
- cocos2dx在Eclipse下编译报错:Cannot find module with tag 'CocosDenshion/android' in import path
在Eclipse下编译cocos2dx项目,报错如下: Android NDK: jni/Android.mk: Cannot find module with tag 'CocosDenshion/ ...
- ASP.NET MVC学习笔记-----Filter2
ASP.NET MVC学习笔记-----Filter(2) 接上篇ASP.NET MVC学习笔记-----Filter(1) Action Filter Action Filter可以基于任何目的使用 ...
- html5基础的常用的技巧
html5基础的常用的技巧 1. 新的Doctype声明 XHTML的声明太长了,我相信很少会有前端开发人员能手写出这个Doctype声明. <!DOCTYPE html PUBLIC &quo ...
- STM8S TIM4 初始化设置
#define TIM4_DIV1 (unsigned char)0 #define TIM4_DIV2 (unsigned char)1 #define TIM4_DIV4 (unsigned ch ...
- jsp传值乱码解决办法
在jsp中,我们经常从数据库读取数据返回客户端,但我们常常在制作时出现乱码现象,所以我们可以用<%request.setCharacterEncoding("UTF-8"); ...
- Linux IO控制命令生成
在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值.cmd除了可区别数字外,还包含有助于处理的几种相应信息. cmd的大小为 32位,共分 4 个 ...
- Windows核心编程学习九:利用内核对象进行线程同步
注:源码为学习<Windows核心编程>的一些尝试,非原创.若能有助于一二访客,幸甚. 1.程序框架 #include "Queue.h" #include <t ...