zoukankan      html  css  js  c++  java
  • C/C++反汇编-各种表达式(加减乘)

    C/C++反汇编-各种表达式(加减乘)

    基于vs2019的反汇编

    优化

    对于vs来说一般的优化有两种方案:

    O1:生成可执行文件空间小

    O2:执行效率高

    在vs2019中的release默认是采用的O2方案来处理也就是执行效率优先,而在debug版本中为了调试比较方便可能就会优化比较少。接下来的反汇编会在release和debug中两个分开呈现

    常量传播

    编译期间会将可计算结果的变量转化为常量来处理

    比如int c = 1;
    printf("%d ",c);
    这里会直接用1来替代c而不是在内存中进行读取

    常量折叠

    当几个常量进行计算的时候,编译器会直接将计算的结果来处理

    int c=1+2-3;

    会直接把c赋值为-1

    加法

    直接上代码

    DEBUG下

        //加法反汇编
    //变量赋值
    int Number1 = 0;
    00C11DE8 mov         dword ptr [Number1],0  
    int Number2 = 0;
    00C11DEF mov         dword ptr [Number2],0  
    //常量加常量
    Number1 = 1 + 2;
    00C11DF6 mov         dword ptr [Number1],3  
    //常量加变量
    Number1 = Number2 + 1;
    00C11DFD mov         eax,dword ptr [Number2]  
    00C11E00 add         eax,1  
    00C11E03 mov         dword ptr [Number1],eax  
    //变量加变量
    Number1 = Number1 + Number2;
    00C11E06 mov         eax,dword ptr [Number1]  
    00C11E09 add         eax,dword ptr [Number2]  
    00C11E0C mov         dword ptr [Number1],eax  

    这里可以看到当两个常量相加的时候,编译器会直接计算值来处理而不是一个一个寄存器来读取,这样会直接减少运行量

     

    Release下

    //加法反汇编
    //变量赋值
    int Number1 = 0;
    int Number2 = 0;
    //常量加常量
    Number1 = 1 + 2;
    //常量加变量
    Number1 = Number2 + 1;
    //变量加变量
    Number1 = Number1 + Number2;

    这里直接没有了那么为什么呢?

    因为这里采用了各种优化,在编译过程中,编译器通常会采用两种优化方式:常量传播和常量折叠来处理

     

    这里可以采用对变量进行不是常量的赋值比如:

    int Number = argc

    argc是main函数中的第一个参数,需要输入才能识别,所以编译器不会将其折叠

    减法

    减法和加法类似,只是对于减法的处理是利用对补码的加法来处理。

     

    乘法

    由于乘法的周期比较长,所以编译器会优先考虑使用加法或者使用位移的方法来处理乘法

    debug下:
    //两常量相乘
    printf("2 * 2 = %d ", 2 * 2);
    00BE43CC push       offset string "2 * 2 = %d " (0BE7CD0h)  
    00BE43D1 call       _main (0BE13C5h)  
    00BE43D6 add         esp,8  
    //混和运算
    printf("Number1*4+5=%d ", Number1 * 4 + 5);
    00BE43D9 mov         eax,dword ptr [Number1]  
    00BE43DC lea         ecx,[eax*4+5]  
    00BE43E3 push       ecx  
    00BE43E4 push       offset string "Number1*4+5=%d " (0BE7CDCh)  
    00BE43E9 call       _main (0BE13C5h)  
    00BE43EE add         esp,8  
    printf("Number1*9+5=%d ", Number1 * 9 + 5);
    00BE43F1 imul       eax,dword ptr [Number1],9  
    00BE43F5 add         eax,5  
    00BE43F8 push       eax  
    00BE43F9 push       offset string "Number1*9+5=%d " (0BE7CECh)  
    00BE43FE call       _main (0BE13C5h)  
    00BE4403 add         esp,8  
    //两个变量相乘
    printf("Number1*Number2=%d ",Number1*Number2);
    00BE4406 mov         eax,dword ptr [Number1]  
    00BE4409 imul       eax,dword ptr [Number2]  
    00BE440D push       eax  
    00BE440E push       offset string "Number1*Number2=%d " (0BE7E20h)  
    00BE4413 call       _main (0BE13C5h)  
    00BE4418 add         esp,8  

     

    在release下的情况:

    //处理不是2的倍数的乘数作为乘法时
    printf("Number1*15=%d ", Number1 * 15);
    00A31044 mov         esi,dword ptr [argc]  
    00A31047 mov         eax,esi  
    00A31049 shl         eax,4  
    00A3104C sub         eax,esi  
    00A3104E push       eax  
    00A3104F push       offset string "Number1*15=%d " (0A32100h)  
    00A31054 call       printf (0A31010h)  
    //处理以2为倍数的乘法作为乘法时
    printf("Number1*16=%d ", Number1 * 16);
    00A31059 mov         eax,esi  
    00A3105B shl         eax,4  
    00A3105E push       eax  
    00A3105F push       offset string "Number1*16=%d " (0A32110h)  
    00A31064 call       printf (0A31010h)  
    //两常量相乘
    printf("2 * 2 = %d ", 2 * 2);
    00A31069 push       4  
    00A3106B push       offset string "2 * 2 = %d " (0A32120h)  
    00A31070 call       printf (0A31010h)  
    //混和运算
    printf("Number1*4+5=%d ", Number1 * 4 + 5);
    00A31075 lea         eax,[esi*4+5]  
    00A3107C push       eax  
    00A3107D push       offset string "Number1*4+5=%d " (0A3212Ch)  
    00A31082 call       printf (0A31010h)  
    printf("Number1*9+5=%d ", Number1 * 9 + 5);
    00A31087 lea         eax,[esi*8+5]  
    00A3108E add         eax,esi  
    00A31090 push       eax  
    00A31091 push       offset string "Number1*9+5=%d " (0A3213Ch)  
    00A31096 call       printf (0A31010h)  
    //两个变量相乘
    printf("Number1*Number2=%d ",Number1*Number2);
    00A3109B imul       esi,esi  
    00A3109E push       esi  
    00A3109F push       offset string "Number1*Number2=%d " (0A3214Ch)  
    00A310A4 call       printf (0A31010h)  
    00A310A9 add         esp,30h  

     

  • 相关阅读:
    How to build Linux system from kernel to UI layer
    Writing USB driver for Android
    Xposed Framework for Android 8.x Oreo is released (in beta)
    Linux Smartphone Operating Systems You Can Install Today
    Librem 5 Leads New Wave of Open Source Mobile Linux Contenders
    GUADEC: porting GNOME to Android
    Librem 5 – A Security and Privacy Focused Phone
    GNOME and KDE Join Librem 5 Linux Smartphone Party
    Purism计划推出安全开源的Linux Librem 5智能手机
    国产系统之殇:你知道的这些系统都是国外的
  • 原文地址:https://www.cnblogs.com/beautiful7/p/14079564.html
Copyright © 2011-2022 走看看