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

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

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

一丶认识构造函数

高级代码:

class MyTest
{
public:
    MyTest();
    ~MyTest();
public:
    DWORD m_dwTest;
};
 MyTest::MyTest()
 {
     printf("1111\r\n");        //构造的时候先打印
     
 }
 MyTest::~MyTest()
 {
    printf("2222\r\n");        //析构的时候打印
 }


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\r\n");
     
 }
 MyTest::~MyTest()
 {
    printf("2222\r\n");
 }


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指针)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java3y

泛型就这么简单

1664
来自专栏nummy

python operator模块学习

operator模块是python中内置的操作符函数接口,它定义了一些算术和比较内置操作的函数。operator模块是用c实现的,所以执行速度比python代码...

822
来自专栏LanceToBigData

异常处理升级版

其实前面就写了一篇异常处理的文章,但是那个文章实在是感觉太详细了,不太好复习。所以今天我就再写一篇这样就更好复习了。 一、异常概述   在我们日常生活中,有时会...

2099
来自专栏博客园

.NET面试题解析(01)-值类型与引用类型

3. delegate是引用类型还是值类型?enum、int[]和string呢?

982
来自专栏Coco的专栏

【优雅代码】深入浅出 妙用Javascript中apply、call、bind

902
来自专栏逆向技术

C++反汇编第三讲,反汇编中识别虚表指针,以及指向的虚函数地址

      C++反汇编第三讲,反汇编中识别虚表指针,以及指向的虚函数地址 讲解之前,了解下什么是虚函数,什么是虚表指针,了解下语法,(也算复习了) 开发知识为...

2486
来自专栏LinkedBear的个人空间

唠唠SE的集合-00——概述 原

                        由于是数组实现,在增和删的时候会牵扯到数组增容、以及拷贝元素,所以慢。

912
来自专栏老九学堂

干货 | Java 中不得不知的异常和处理详解

简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用...

4027
来自专栏mukekeheart的iOS之旅

OC学习6——面相对象的三大特性

我们在学习Java的时候都知道,类有三大特性:继承,封装,多态,这也是面向对象的三大特征。OC学习篇之---类的三大特性(封装,继承,多态) 1、封装(Enca...

2878
来自专栏逆向技术

C语言第四讲,typedef 关键字,以及作用域

        C语言第四讲,typedef 关键字,以及作用域 一丶typedef关键字   在C语言中,有typedef 关键字,这个关键字的作用就是允许你...

2875

扫码关注云+社区

领取腾讯云代金券