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  

     

  • 相关阅读:
    COM学习(三)——数据类型
    com学习(一)GUID 和 接口
    Dll学习(二)__declspec用法详解
    dll 学习(一)
    PostMessage与SendMessage的区别(二)
    sendmessage和postmessage的区别
    用Java开发代理服务器
    JAVA编写WEB服务器
    【1.3】Django HelloWorld
    【1.2】初识Django应用
  • 原文地址:https://www.cnblogs.com/beautiful7/p/14079564.html
Copyright © 2011-2022 走看看