cpp反汇编之继承之基类

先分析一个例子。

#include<stdio.h>

class CBase
{
public:
	CBase()
	{
		printf("CBase\n");
	}
	~CBase()
	{
		printf("~CBase\n");
	}
	void SetNumber(int nInt)
	{
		this->m_nNumber = nInt;
	}
	int GetNumber()
	{
		return this->m_nNumber;
	}
private:
	int m_nNumber;
};

class CDerive : public CBase
{
public:
	void ShowNumber(int nNumber)
	{
		SetNumber(nNumber);
		m_nDerive = nNumber + 1;
		printf("%d\n" , GetNumber());
		printf("%d\n" , m_nDerive);
	}
public:
	int m_nDerive;
};

int main1(int argc , char *argv[])
{
	CDerive derive;
	derive.ShowNumber(argc);
	return 0;
}
int main3()
{
	int nTest = 0x87654321;
	CBase base;
	CDerive *pDerive = (CDerive *)(&base);
	printf("%x\n" , pDerive->m_nDerive);
	return 0;
}

下面是反汇编分析

此处是函数跳转表
@ILT+0([email protected]@@[email protected]):
00401005   jmp         CBase::SetNumber (00401190)
@ILT+5([email protected]@[email protected]):
0040100A   jmp         CBase::~CBase (00401300)
@ILT+10([email protected]@@[email protected]):
0040100F   jmp         CDerive::ShowNumber (00401100)
@ILT+15([email protected]@@QAEHXZ):
00401014   jmp         CBase::GetNumber (004011d0)
@ILT+20([email protected]@[email protected]):
00401019   jmp         CDerive::CDerive (00401210)
@ILT+25([email protected]@[email protected]):
0040101E   jmp         CDerive::~CDerive (004012b0)
@ILT+30(_main):
00401023   jmp         main (00401060)
@ILT+35([email protected]@[email protected]):
00401028   jmp         CBase::CBase (00401260)

CDerive::CDerive:
00401210   push        ebp
00401211   mov         ebp,esp
00401213   sub         esp,44h
00401216   push        ebx
00401217   push        esi
00401218   push        edi
00401219   push        ecx
0040121A   lea         edi,[ebp-44h]
0040121D   mov         ecx,11h
00401222   mov         eax,0CCCCCCCCh
00401227   rep stos    dword ptr [edi]
00401229   pop         ecx
0040122A   mov         dword ptr [ebp-4],ecx     ecx即为this指针
0040122D   mov         ecx,dword ptr [ebp-4]
00401230   call        @ILT+35(CBase::CBase) (00401028)
00401235   mov         eax,dword ptr [ebp-4]
00401238   pop         edi
00401239   pop         esi
0040123A   pop         ebx
0040123B   add         esp,44h
0040123E   cmp         ebp,esp
00401240   call        __chkesp (00401730)
00401245   mov         esp,ebp
00401247   pop         ebp
00401248   ret

CDerive::~CDerive:
004012B0   push        ebp
004012B1   mov         ebp,esp
004012B3   sub         esp,44h
004012B6   push        ebx
004012B7   push        esi
004012B8   push        edi
004012B9   push        ecx
004012BA   lea         edi,[ebp-44h]
004012BD   mov         ecx,11h
004012C2   mov         eax,0CCCCCCCCh
004012C7   rep stos    dword ptr [edi]
004012C9   pop         ecx
004012CA   mov         dword ptr [ebp-4],ecx
004012CD   mov         ecx,dword ptr [ebp-4]
004012D0   call        @ILT+5(CBase::~CBase) (0040100a)
004012D5   pop         edi
004012D6   pop         esi
004012D7   pop         ebx
004012D8   add         esp,44h
004012DB   cmp         ebp,esp
004012DD   call        __chkesp (00401730)
004012E2   mov         esp,ebp
004012E4   pop         ebp
004012E5   ret

1:    #include<stdio.h>
2:
3:    class CBase
4:    {
5:    public:
6:        CBase()
00401260   push        ebp
00401261   mov         ebp,esp
00401263   sub         esp,44h
00401266   push        ebx
00401267   push        esi
00401268   push        edi
00401269   push        ecx
0040126A   lea         edi,[ebp-44h]
0040126D   mov         ecx,11h
00401272   mov         eax,0CCCCCCCCh
00401277   rep stos    dword ptr [edi]
00401279   pop         ecx
0040127A   mov         dword ptr [ebp-4],ecx
7:        {
8:            printf("CBase\n");
0040127D   push        offset string "CBase\n" (00425020)
00401282   call        printf (00401860)
00401287   add         esp,4
9:        }
0040128A   mov         eax,dword ptr [ebp-4]
0040128D   pop         edi
0040128E   pop         esi
0040128F   pop         ebx
00401290   add         esp,44h
00401293   cmp         ebp,esp
00401295   call        __chkesp (00401730)
0040129A   mov         esp,ebp
0040129C   pop         ebp
0040129D   ret

10:       ~CBase()
11:       {
00401300   push        ebp
00401301   mov         ebp,esp
00401303   sub         esp,44h
00401306   push        ebx
00401307   push        esi
00401308   push        edi
00401309   push        ecx
0040130A   lea         edi,[ebp-44h]
0040130D   mov         ecx,11h
00401312   mov         eax,0CCCCCCCCh
00401317   rep stos    dword ptr [edi]
00401319   pop         ecx              还原ecx指针
0040131A   mov         dword ptr [ebp-4],ecx
12:           printf("~CBase\n");
0040131D   push        offset string "~CBase\n" (00425028)
00401322   call        printf (00401860)
00401327   add         esp,4
13:       }
0040132A   pop         edi
0040132B   pop         esi
0040132C   pop         ebx
0040132D   add         esp,44h
00401330   cmp         ebp,esp
00401332   call        __chkesp (00401730)
00401337   mov         esp,ebp
00401339   pop         ebp
0040133A   ret

14:       void SetNumber(int nInt)
15:       {
00401190   push        ebp
00401191   mov         ebp,esp
00401193   sub         esp,44h
00401196   push        ebx
00401197   push        esi
00401198   push        edi
00401199   push        ecx
0040119A   lea         edi,[ebp-44h]
0040119D   mov         ecx,11h
004011A2   mov         eax,0CCCCCCCCh
004011A7   rep stos    dword ptr [edi]
004011A9   pop         ecx
004011AA   mov         dword ptr [ebp-4],ecx
16:           this->m_nNumber = nInt;
004011AD   mov         eax,dword ptr [ebp-4]
004011B0   mov         ecx,dword ptr [ebp+8]
004011B3   mov         dword ptr [eax],ecx
17:       }
004011B5   pop         edi
004011B6   pop         esi
004011B7   pop         ebx
004011B8   mov         esp,ebp
004011BA   pop         ebp
004011BB   ret         4

18:       int GetNumber()
19:       {
004011D0   push        ebp
004011D1   mov         ebp,esp
004011D3   sub         esp,44h
004011D6   push        ebx
004011D7   push        esi
004011D8   push        edi
004011D9   push        ecx
004011DA   lea         edi,[ebp-44h]
004011DD   mov         ecx,11h
004011E2   mov         eax,0CCCCCCCCh
004011E7   rep stos    dword ptr [edi]
004011E9   pop         ecx
004011EA   mov         dword ptr [ebp-4],ecx
20:           return this->m_nNumber;
004011ED   mov         eax,dword ptr [ebp-4]
004011F0   mov         eax,dword ptr [eax]
21:       }
004011F2   pop         edi
004011F3   pop         esi
004011F4   pop         ebx
004011F5   mov         esp,ebp
004011F7   pop         ebp
004011F8   ret

22:   private:
23:       int m_nNumber;
24:   };
25:
26:   class CDerive : public CBase
27:   {
28:   public:
29:       void ShowNumber(int nNumber)
30:       {
00401100   push        ebp
00401101   mov         ebp,esp
00401103   sub         esp,44h
00401106   push        ebx
00401107   push        esi
00401108   push        edi
00401109   push        ecx
0040110A   lea         edi,[ebp-44h]
0040110D   mov         ecx,11h
00401112   mov         eax,0CCCCCCCCh
00401117   rep stos    dword ptr [edi]
00401119   pop         ecx
0040111A   mov         dword ptr [ebp-4],ecx
31:           SetNumber(nNumber);
0040111D   mov         eax,dword ptr [ebp+8]
00401120   push        eax
00401121   mov         ecx,dword ptr [ebp-4]
00401124   call        @ILT+0(CBase::SetNumber) (00401005)
32:           m_nDerive = nNumber + 1;
00401129   mov         ecx,dword ptr [ebp+8]
0040112C   add         ecx,1
0040112F   mov         edx,dword ptr [ebp-4]
00401132   mov         dword ptr [edx+4],ecx
33:           printf("%d\n" , GetNumber());
00401135   mov         ecx,dword ptr [ebp-4]
00401138   call        @ILT+15(CBase::GetNumber) (00401014)
0040113D   push        eax
0040113E   push        offset string "%d\n" (0042501c)
00401143   call        printf (00401860)
00401148   add         esp,8
34:           printf("%d\n" , m_nDerive);
0040114B   mov         eax,dword ptr [ebp-4]
0040114E   mov         ecx,dword ptr [eax+4]
00401151   push        ecx
00401152   push        offset string "%d\n" (0042501c)
00401157   call        printf (00401860)
0040115C   add         esp,8
35:       }
0040115F   pop         edi
00401160   pop         esi
00401161   pop         ebx
00401162   add         esp,44h
00401165   cmp         ebp,esp
00401167   call        __chkesp (00401730)
0040116C   mov         esp,ebp
0040116E   pop         ebp
0040116F   ret         4

36:   private:
37:       int m_nDerive;
38:   };
39:
40:   int main(int argc , char *argv[])
41:   {
00401060   push        ebp
00401061   mov         ebp,esp
00401063   push        0FFh
00401065   push        offset __ehhandler$_main (00413429)
0040106A   mov         eax,fs:[00000000]
00401070   push        eax
00401071   mov         dword ptr fs:[0],esp
00401078   sub         esp,4Ch
0040107B   push        ebx
0040107C   push        esi
0040107D   push        edi
0040107E   lea         edi,[ebp-58h]
00401081   mov         ecx,13h
00401086   mov         eax,0CCCCCCCCh
0040108B   rep stos    dword ptr [edi]
42:       CDerive derive;
0040108D   lea         ecx,[ebp-14h]
00401090   call        @ILT+20(CDerive::CDerive) (00401019)
00401095   mov         dword ptr [ebp-4],0
43:       derive.ShowNumber(argc);
0040109C   mov         eax,dword ptr [ebp+8]
0040109F   push        eax
004010A0   lea         ecx,[ebp-14h]
004010A3   call        @ILT+10(CDerive::ShowNumber) (0040100f)
44:       return 0;
004010A8   mov         dword ptr [ebp-18h],0
004010AF   mov         dword ptr [ebp-4],0FFFFFFFFh
004010B6   lea         ecx,[ebp-14h]
004010B9   call        @ILT+25(CDerive::~CDerive) (0040101e)
004010BE   mov         eax,dword ptr [ebp-18h]
45:   }
004010C1   mov         ecx,dword ptr [ebp-0Ch]
004010C4   mov         dword ptr fs:[0],ecx
004010CB   pop         edi
004010CC   pop         esi
004010CD   pop         ebx
004010CE   add         esp,58h
004010D1   cmp         ebp,esp
004010D3   call        __chkesp (00401730)
004010D8   mov         esp,ebp
004010DA   pop         ebp
004010DB   ret

父类有构造函数子类没有则编译器提供一个默认的。子类有父类没有则不一定提供。除非有虚函数等。

46:   int main()
47:   {
00401360   push        ebp
00401361   mov         ebp,esp
00401363   sub         esp,50h
00401366   push        ebx
00401367   push        esi
00401368   push        edi
00401369   lea         edi,[ebp-50h]
0040136C   mov         ecx,14h
00401371   mov         eax,0CCCCCCCCh
00401376   rep stos    dword ptr [edi]
48:       int nTest = 0x87654321;
00401378   mov         dword ptr [ebp-4],87654321h
49:       CBase base;
0040137F   lea         ecx,[ebp-8]
00401382   call        @ILT+40(CBase::CBase) (0040102d)
50:       CDerive *pDerive = (CDerive *)(&base);
00401387   lea         eax,[ebp-8]
0040138A   mov         dword ptr [ebp-0Ch],eax
51:       printf("%x\n" , pDerive->m_nDerive);
0040138D   mov         ecx,dword ptr [ebp-0Ch]
00401390   mov         edx,dword ptr [ecx+4]		//指针偏移,注意此处是指针偏移,指针可以为NULL  NULL + 4不是NULL,不会出现空指针异常
00401393   push        edx
00401394   push        offset string "%x\n" (00425034)
00401399   call        printf (00401930)
0040139E   add         esp,8
52:       return 0;
004013A1   mov         dword ptr [ebp-10h],0
004013A8   lea         ecx,[ebp-8]
004013AB   call        @ILT+5(CBase::~CBase) (0040100a)
004013B0   mov         eax,dword ptr [ebp-10h]
53:   }
004013B3   pop         edi
004013B4   pop         esi
004013B5   pop         ebx
004013B6   add         esp,50h
004013B9   cmp         ebp,esp
004013BB   call        __chkesp (00401800)
004013C0   mov         esp,ebp
004013C2   pop         ebp
004013C3   ret
时间: 2024-10-21 10:28:07

cpp反汇编之继承之基类的相关文章

C++的继承操作---基类指针访问派生类问题---基类成员恢复访问属性问题

#include "stdafx.h" #include <iostream> #include <algorithm> using namespace std; class Base { public: int num; virtual void func() { cout<<"Do something in Base"<<endl; } }; class Derived:private Base { public:

修改tt模板让ADO.NET C# POCO Entity Generator With WCF Support 生成的实体类继承自定义基类

折腾几天记载一下,由于项目实际需要,从edmx生成的实体类能自动继承自定义的基类,这个基类不是从edmx文件中添加的Entityobject. 利用ADO.NET C# POCO Entity Generator With WCF Support生成的tt文件(比如model.tt)中找到 partial class partial class 修改tt模板让ADO.NET C# POCO Entity Generator With WCF Support 生成的实体类继承自定义基类

servlet、filter、listener继承的基类和获得作用域的方式

一.servlet: 1.servlet属于j2ee的组件,构建servlet的web project不需要导入项目框架jar包 2.servlet的体系结构:  在j2ee API中,提供给servlet的支持接口和基类都位于javax.servlet.*和javax.servlet.http.*(提供所有与http请求有关的API)两个包中  servlet包中常使用的接口   Interface ServletConfig   Interface ServletContext   Inte

继承,基类,派生类

在 C++中,继承机制通过类的派生实现,被继承的类称为基类或父类:在继承类的基础上创建的新类称为派生类或子类.派生类的定义格式为:class 派生类名:继承方式基类名 1,继承方式基类名 2,…,继承方式基类名 n{派生类增加的成员声明;};其中,定义中的基类名必须是已有类的名称,派生类名则是新建的类名.一个派生类可以只有一个基类,称为单继承:也可以同时有多个基类,称为多继承.派生类也可作为基类继续派生子类.

Python_64类的继承之基类构造方法

class A: def bar(self): print ('A-BAR') self.f1()class B(A): def f1(self): print ('B')class C: def f1(self): print ('C') class D(C,B): passd1=D()d1.bar()输出-----------------------------------------------------------------------------------------------

从设计基类及其派生类看继承关系

继承能够定义可重用.扩展或修改父类行为的子类.但基类的静态构造函数.实例构造函数和析构函数不能被派生类继承. 在下面实例中,定义一个基类Publication用于表示任何类型的出版物以及派生至Publication的其他类型Book类,由此也可以扩展为定义其他类型如:Magazine.Journal.Newspaper和Article. 在设计基类Publication时我们必须考虑到如下关系: 1.要在基类中添加哪些成员 2.基类是否用作派生类模板的抽象基类 3.类层次结构的扩展空间大小,要开

5、继承与派生6-虚基类

当某类的部分或全部直接基类是从另一个共同基类派生而来时,在这些直接基类中从上一级共同基类继承来的成员就拥有相同的名称.在派生类的对象中,这些同名数据成员在内存中同时拥有多个拷贝,同一个函数名会有多个映射.我们可以使用作用域分辨符来惟一标识并分别访问他们,也可以将共同基类设置为虚基类,这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射.这样就解决了同名成员的惟一标识问题. 虚基类的声明是在派生类的定义过程中进行的,语法形式: class 派生类名:virtua

C++ Primer学习笔记32_面向对象编程(3)--继承(三):多重继承、虚继承与虚基类

C++ Primer学习笔记32_面向对象编程(3)--继承(三):多重继承.虚继承与虚基类 一.多重继承 在C++语言中,一个派生类可以从一个基类派生,称为单继承:也可以从多个基类派生,称为多继承. 多重继承--一个派生类可以有多个基类 class <派生类名> : <继承方式1> <基类名1>,<继承方式2> <基类名2>,... { <派生类新定义成员> }; 可见,多继承与单继承的区别从定义格式上看,主要是多继承的基类多于一个

子类继承基类的三种继承方式

在C++中,子类继承父类有三种继承方式,分别是:public, protected和private.子类继承的方式不同,那么子类对象访问父类中的参数访问权限也不同. public 方式继承:基类的private成员派生类不可见,基类中的protected和public成员在派生类中可以直接使用,并且变成了派生类中相应                        的protected成员和public成员,但是只有public成员可以在派生类外使用. protected 方式继承:基类的priv