zoukankan      html  css  js  c++  java
  • C++反汇编第一讲,认识构造函数,析构函数,以及成员函数

              C++反汇编第一讲,认识构造函数,析构函数,以及成员函数

    以前说过在C系列下的汇编,怎么认识函数.那么现在是C++了,隐含有构造和析构函数

    一丶认识构造函数

    高级代码:

      

    class MyTest
    {
    public:
        MyTest();
        ~MyTest();
    public:
        DWORD m_dwTest;
    };
     MyTest::MyTest()
     {
         printf("1111
    ");        //构造的时候先打印
         
     }
     MyTest::~MyTest()
     {
        printf("2222
    ");        //析构的时候打印
     }
    
    
    int main(int argc, char* argv[])
    {
        MyTest Test;              //创建局部对象
        getchar();
        return 0;
    }

    C++中的类,构造的时候先祖先类,然后父类,最后朋友类,然后在构造自己.  析构的时候 先自己 后朋友 接着父类 然后是祖先类,(明白一下顺序)

    Debug下的汇编代码

      

    这个是main函数内部,在创建对象的时候,会先调用构造,然后退出的时候会调用析构(上面是我改名字过后的)

    现在我们认识构造有几个必要条件

    1.ecx,this传参因为C++下的对象都是 thisCall,和FastCall类似,thisCall会通过寄存器传参.而fastCall最后两个参数会通过寄存器传参.

    .鉴定是ecx传参的前提下是函数外面给值,函数内部使用

    函数内部会将ecx给存储起来,这个内存空间称之为  this,也就是语法为什么可以这样写: this.xxxx = 1  this.MyTest();

    高亮ecx传参的时候的内存地址,会有多处使用. 

    2.构造会在创建对象的时候先调用

    3.构造函数的返回值则是this指针.

    详解怎么查看构造函数

    1.是ecx传参,确定了一个条件,其余两个条件还没有满足

    2.函数内部使用ecx,且给this指针赋值,并且返回了this指针

    返回的汇编: 

    3.该函数是当前栈作用域下的第一次调用

      

    main函数中初始化成员变量为ccc之后,调用的第一个.

    PS: 附加条件 我们点击ecx传参的时候的局部变量(this)会有多处使用.

    一般来说确定上面三点则可以确定是构造函数了.上面三个都是必要条件.

    而充分条件以后学习虚表的时候就知道了,构造会初始化虚表,且是第一个,所以可以直接确定是构造函数了.

    说的听过,其实看反汇编代码也就3 - 4秒的事情.

    Release下的汇编

    根据上面代码,可以确定

    1.先调用的第一个函数

    2.ecx传参.并且内部使用了ecx,赋值给了this指针,且把this指针返回

     注意:构造函数,析构函数只能是thiscall,就算你自己加上调用约定,编译的时候也提示是无效的调用约定,且反汇编代码不会做任何改变.

    总结:

      1.构造函数优先调用

      2.ecx传参,且函数内部会将ecx给this赋值(this可能是一块内存空间,也可能是寄存器变量)且返回this指针

      3.可以点击this指针,可能会有多次调用

    注: 构造析构都是thiscall,不能修改

     二丶识别析构函数

    识别析构函数和构造函数类似

    1.thiscall,并且最后调用

    2.无返回值

    看下析构函数

    1.最后一次调用的

      

    2.thiscall,无返回值,其内部会使用ecx给this赋值

      

     Release下的汇编和Debug下一样,有优化,可能你不使用this则不会给this赋值.但是还是无返回值

     总结:

      1.析构最后一次调用

      2.thiscall传参

      3.无返回值

    三丶识别成员函数(c call  thiscall  fastcall  stdcall)

    高级代码:

      

    class MyTest
    {
    public:
        MyTest();
        ~MyTest();
        void SetTest(DWORD dwTest);
        DWORD GetTest();
    public:
        DWORD m_dwTest;
    };
     MyTest::MyTest()
     {
         printf("1111
    ");
         
     }
     MyTest::~MyTest()
     {
        printf("2222
    ");
     }
    
    
    void MyTest::SetTest(DWORD dwTest)
    {
        this->m_dwTest = dwTest;   
    }
    DWORD MyTest::GetTest()
    {
        return this->m_dwTest;
    }
    int main(int argc, char* argv[])
    {
        MyTest Test;
        Test.SetTest(1);      
        int Number = Test.GetTest();      //添加了Set,Get方法,并调用
        getchar();
        return 0;
    }

    看上面,我们可以看出都是默认的thiscall,看下反汇编代码 (看各种调用约定会产生什么样的结果)

    1.默认的thiscall在汇编中的表现形式

    Debug下的反汇编

    头尾是构造和析构,中间则是我们的SetGet方法,可以看出,如果是thiscall,那么是ecx传参,且里面ecx会给this指针赋值,且返回this指针

    Release和Debug类似,可能有少许优化,为了篇幅原因,不在截图. 

    2.Stdcall 成员函数表现形式

    看上面汇编代码得出

    1.this指针是  ebp + var_10,

    2.在stdcall下,会将this指针给寄存器,然后push进去

    总结:

      1.stdcall 会将this指针当做参数push进去.

      2. push进去的this指针,会在call上面第一个push,也就是说this指针是第一个参数

      3.平栈还是按照stdcall的形式平栈

     3.C call下的汇编表现形式

      

    也是通过push的方式,将this指针当做参数传递

    然后c调用约定在外面平栈

    4.fastCall的汇编表现形式

     寄存器传参,然后ecx是外部更改,内部使用

    最终的大总结:

        1).识别构造

          1.构造函数优先调用

          2.ecx传参,且函数内部会将ecx给this赋值(this可能是一块内存空间,也可能是寄存器变量)且返回this指针

          3.可以点击this指针,可能会有多次调用

          注: 构造析构都是thiscall,不能修改

        2).识别析构

          1.析构最后一次调用

          2.thiscall传参

          3.无返回值

      

        3).识别各种调用约定的成员函数

           1.c调用约定,会将this指针push进去,然后平栈按照c调用约定平栈

           2.stdcall,会将this指针push进去,内部平栈

          3.thiscall会默认使用ecx,外部更改,内部使用,平栈和stdcall一样

          4.fastcall,会使用两个寄存器传参,且也会外部更改ecx,内部使用.

          5.c约定,std约定,push的时候都是this指针,且是第一个参数(也就是call上面的最近的一个push,必定为this指针)

       

  • 相关阅读:
    抽象类与接口 【转载】
    linux网卡驱动程序架构
    linux回环网卡驱动设计
    命令行启动appium服务
    Java+Maven的工程运行Sonar的方式
    使用Fabric在tomcat中部署应用的问题总结
    Fabric的使用总结
    利用xcode Build生成模拟器运行包
    Jenkins配置git/github 插件的ssh key
    Jenkins插件--通知Notification
  • 原文地址:https://www.cnblogs.com/iBinary/p/7966821.html
Copyright © 2011-2022 走看看