zoukankan      html  css  js  c++  java
  • 《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# Linq获取两个List或数组的差集交集
    C# List排序,附加使用Linq排序
    C#Qrcode生成二维码支持中文,带图片,带文字
    C#判断本地文件,网络文件是否存在是否存在
    C#WebBrowser控件使用教程与技巧收集
  • 原文地址:https://www.cnblogs.com/predator-wang/p/6283460.html
Copyright © 2011-2022 走看看