在C++中,结构体和类都具有构造函数、析构函数和成员函数,两者只有一个区别:结构体的访问控制默认为public,而类的默认访问控制是private。
对于C++中的结构体而言,public、private、protected的访问控制都是在编译期进行检查,当越权访问时,编译过程中会检查出此类错误并给予提示。
编译成功后,程序在执行的过程中不会在访问控制方面做任何检查和限制。因此,在反汇编中,C++中的结构体与类没有分别,两者的原理相同,只是类型名称不同,
- 静态数据成员和普通数据成员
// 含有静态数据成员的类
class CStatic
{
public:
void ShowNumber()
{
printf("m_nInt = %d , m_snInt = %d", m_nInt, m_snInt);
}
static int m_snInt;
int m_nInt;
};
int CStatic::m_snInt = 5;
208: CStatic Static; 209: int nSize = sizeof(Static); 01083646 C7 45 B4 04 00 00 00 mov dword ptr [nSize],4 210: printf("CStatic : %d ", nSize); 0108364D 8B 45 B4 mov eax,dword ptr [nSize] 01083650 50 push eax 01083651 68 78 3E 11 01 push offset string "CStatic : %d " (01113E78h) 01083656 E8 6A DD FE FF call _printf (010713C5h) 0108365B 83 C4 08 add esp,8 211: 212: printf("0x%08x ", &Static.m_snInt); 0108365E 68 00 80 13 01 push offset CStatic::m_snInt (01138000h) //静态成员变量,与全局变量相似 01083663 68 B4 3E 11 01 push offset string "0x%08x " (01113EB4h) 01083668 E8 58 DD FE FF call _printf (010713C5h) 0108366D 83 C4 08 add esp,8 213: printf("0x%08x ", &Static.m_nInt); 01083670 8D 45 C0 lea eax,[Static] //普通成员变量, 01083673 50 push eax 01083674 68 B4 3E 11 01 push offset string "0x%08x " (01113EB4h) 01083679 E8 47 DD FE FF call _printf (010713C5h) 0108367E 83 C4 08 add esp,8 214: 215: Static.m_nInt = 1; 01083681 C7 45 C0 01 00 00 00 mov dword ptr [Static],1 //普通成员变量赋值 216: Static.m_snInt = 2; 01083688 C7 05 00 80 13 01 02 00 00 00 mov dword ptr [CStatic::m_snInt (01138000h)],2 //静态成员函数赋值 217: Static.ShowNumber(); 01083692 8D 4D C0 lea ecx,[Static] 01083695 E8 30 F6 FE FF call CStatic::ShowNumber (01072CCAh)
- 对象作为函数参数
class CFunTest
{
public:
void ShowNumber()
{
printf("%d %d %s
", m_nOne, m_nTwo, m_szName);
}
int m_nOne;
int m_nTwo;
char m_szName[32];
};
void ShowFunTest(CFunTest FunTest)
{
//FunTest.ShowNumber();
printf("%d %d %s
",
FunTest .m_nOne, FunTest.m_nTwo, FunTest .m_szName);
}
219: //对象作为函数参数 220: CFunTest FunTest; 221: FunTest.m_nOne = 1; 0108369A C7 45 84 01 00 00 00 mov dword ptr [FunTest],1 222: FunTest.m_nTwo = 2; 010836A1 C7 45 88 02 00 00 00 mov dword ptr [ebp-78h],2 223: strcpy(FunTest.m_szName, "Name"); 010836A8 68 A0 3E 11 01 push offset string "Name" (01113EA0h) 010836AD 8D 45 8C lea eax,[ebp-74h] 010836B0 50 push eax 010836B1 E8 FB FA FE FF call _strcpy (010731B1h) 010836B6 83 C4 08 add esp,8 224: ShowFunTest(FunTest); 010836B9 83 EC 28 sub esp,28h //CFunTest类大小为40字节,开辟栈空间,存储参数对象(相当于形参) 010836BC B9 0A 00 00 00 mov ecx,0Ah 010836C1 8D 75 84 lea esi,[FunTest] 010836C4 8B FC mov edi,esp 010836C6 F3 A5 rep movs dword ptr es:[edi],dword ptr [esi] //浅拷贝,将参数对象拷贝到局部栈空间中;(如果有拷贝构造的话,此处调用) 010836C8 E8 4B 02 FF FF call ShowFunTest (01073918h) 010836CD 83 C4 28 add esp,28h
对象中存在资源释放时,做为函数参数
// 带有资源申请与释放的类
class CMyString
{
public:
CMyString(){
m_pString = new char[10];
if (m_pString == NULL){
return;
}
strcpy(m_pString, "Hello");
}
~CMyString(){
if (m_pString != NULL){
delete m_pString;
m_pString = NULL;
}
}
char * GetString(){
return m_pString;
}
void SetString(char * pString)
{
int nLen = strlen(pString);
if (m_pString != NULL)
{
delete [] m_pString;
m_pString = NULL;
}
m_pString = new char[nLen + sizeof(char)];
strcpy(m_pString, pString);
}
private:
char * m_pString;
};
227: //对象中存在资源释放时,做为函数参数 228: CMyString MyString; 010836D0 8D 8D 78 FF FF FF lea ecx,[MyString] 010836D6 E8 28 E5 FE FF call CMyString::CMyString (01071C03h) 010836DB C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0 //当前作用域对象数量 229: ShowMyString(MyString); 010836E2 8B 85 78 FF FF FF mov eax,dword ptr [MyString] //类CMyString大小为4字节,只有一项数据成员m_pString 010836E8 50 push eax //相当于对象参数浅拷贝到局部空间中 010836E9 E8 5C 07 FF FF call ShowMyString (01073E4Ah) 010836EE 83 C4 04 add esp,4 230: ShowMyString(MyString); 010836F1 8B 85 78 FF FF FF mov eax,dword ptr [MyString] 010836F7 50 push eax 010836F8 E8 4D 07 FF FF call ShowMyString (01073E4Ah) //再次调用,函数内调用了析构函数,其中使用delete将资源释放,程序发生异常 010836FD 83 C4 04 add esp,4
…………main函数退出时
0108379B C7 45 FC FF FF FF FF mov dword ptr [ebp-4],0FFFFFFFFh //对象计数 010837A2 8D 8D 78 FF FF FF lea ecx,[MyString] 010837A8 E8 5B F3 FE FF call CMyString::~CMyString (01072B08h) //析构 010837AD 33 C0 xor eax,eax 010837AF 52 push edx 010837B0 8B CD mov ecx,ebp 010837B2 50 push eax 010837B3 8D 15 EC 37 08 01 lea edx,ds:[10837ECh] 010837B9 E8 86 F8 FE FF call @_RTC_CheckStackVars@8 (01073044h) 010837BE 58 pop eax 010837BF 5A pop edx 010837C0 8B 4D F4 mov ecx,dword ptr [ebp-0Ch] 010837C3 64 89 0D 00 00 00 00 mov dword ptr fs:[0],ecx 010837CA 59 pop ecx 010837CB 5F pop edi 010837CC 5E pop esi 010837CD 5B pop ebx 010837CE 8B 4D F0 mov ecx,dword ptr [ebp-10h] 010837D1 33 CD xor ecx,ebp 010837D3 E8 85 F3 FE FF call @__security_check_cookie@4 (01072B5Dh) 010837D8 81 C4 10 02 00 00 add esp,210h 010837DE 3B EC cmp ebp,esp 010837E0 E8 F7 F6 FE FF call __RTC_CheckEsp (01072EDCh) 010837E5 8B E5 mov esp,ebp 010837E7 5D pop ebp 010837E8 C3 ret
void ShowMyString(CMyString MyStringCpy)
151: void ShowMyString(CMyString MyStringCpy) 152: { 010773E0 55 push ebp 010773E1 8B EC mov ebp,esp 010773E3 6A FF push 0FFFFFFFFh 010773E5 68 08 15 11 01 push 1111508h 010773EA 64 A1 00 00 00 00 mov eax,dword ptr fs:[00000000h] 010773F0 50 push eax 010773F1 81 EC C0 00 00 00 sub esp,0C0h 010773F7 53 push ebx 010773F8 56 push esi 010773F9 57 push edi 010773FA 8D BD 34 FF FF FF lea edi,[ebp-0CCh] 01077400 B9 30 00 00 00 mov ecx,30h 01077405 B8 CC CC CC CC mov eax,0CCCCCCCCh 0107740A F3 AB rep stos dword ptr es:[edi] 0107740C A1 08 80 13 01 mov eax,dword ptr [__security_cookie (01138008h)] 01077411 33 C5 xor eax,ebp 01077413 50 push eax 01077414 8D 45 F4 lea eax,[ebp-0Ch] 01077417 64 A3 00 00 00 00 mov dword ptr fs:[00000000h],eax 0107741D C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0 //当前域对象计数 153: printf(MyStringCpy.GetString()); 01077424 8D 4D 08 lea ecx,[MyStringCpy] //取对象参数的地址, [ecx](ecx所指内存中数据)是对象参数的成员数据m_pString,由于只是简单的复制,所以与原对象中的值相同。 01077427 E8 06 A1 FF FF call CMyString::GetString (01071532h) 153: printf(MyStringCpy.GetString()); 0107742C 50 push eax 0107742D E8 93 9F FF FF call _printf (010713C5h) 01077432 83 C4 04 add esp,4 154: } 01077435 C7 45 FC FF FF FF FF mov dword ptr [ebp-4],0FFFFFFFFh //对象计数 0107743C 8D 4D 08 lea ecx,[MyStringCpy] 0107743F E8 C4 B6 FF FF call CMyString::~CMyString (01072B08h) 01077444 8B 4D F4 mov ecx,dword ptr [ebp-0Ch] 01077447 64 89 0D 00 00 00 00 mov dword ptr fs:[0],ecx 0107744E 59 pop ecx 0107744F 5F pop edi 01077450 5E pop esi 01077451 5B pop ebx 01077452 81 C4 CC 00 00 00 add esp,0CCh 01077458 3B EC cmp ebp,esp 0107745A E8 7D BA FF FF call __RTC_CheckEsp (01072EDCh) 0107745F 8B E5 mov esp,ebp 01077461 5D pop ebp 01077462 C3 ret
- 对象作为返回值
class CReturn
{
public:
int m_nNumber;
int m_nArry[10];
};
// 对象作为返回值
CReturn GetCReturn()
{
CReturn Return ;
Return.m_nNumber = 0;
for (int i = 0; i < 10; i++)
{
Return.m_nArry[i] = i+1;
}
return Return;
}
233: //返回值为对象 234: CReturn Return; 235: Return = GetCReturn(); 012136F1 8D 85 F4 FD FF FF lea eax,[ebp-20Ch] //开辟的返回对象空间地址 012136F7 50 push eax 012136F8 E8 F3 FC FE FF call GetCReturn (012033F0h) 012136FD 83 C4 04 add esp,4 01213700 B9 0B 00 00 00 mov ecx,0Bh 01213705 8B F0 mov esi,eax 01213707 8D BD 28 FE FF FF lea edi,[ebp-1D8h] //临时对象地址 0121370D F3 A5 rep movs dword ptr es:[edi],dword ptr [esi] //返回对象浅复制到临时对象 0121370F B9 0B 00 00 00 mov ecx,0Bh 01213714 8D B5 28 FE FF FF lea esi,[ebp-1D8h] 0121371A 8D BD 44 FF FF FF lea edi,[Return] 01213720 F3 A5 rep movs dword ptr es:[edi],dword ptr [esi] //临时对象浅复制到Return 236: printf("%d %d %d", Return.m_nNumber, Return.m_nArry[0], Return.m_nArry[9]); 01213722 B8 04 00 00 00 mov eax,4 01213727 6B C8 09 imul ecx,eax,9 0121372A 8B 94 0D 48 FF FF FF mov edx,dword ptr [ebp+ecx-0B8h] //m_nArry[9] 01213731 52 push edx 01213732 B8 04 00 00 00 mov eax,4 01213737 6B C8 00 imul ecx,eax,0 0121373A 8B 94 0D 48 FF FF FF mov edx,dword ptr [ebp+ecx-0B8h] //m_nArry[0] 01213741 52 push edx 01213742 8B 85 44 FF FF FF mov eax,dword ptr [Return] 01213748 50 push eax 236: printf("%d %d %d", Return.m_nNumber, Return.m_nArry[0], Return.m_nArry[9]); 01213749 68 D4 3E 2A 01 push offset string "%d %d %d" (012A3ED4h) 0121374E E8 72 DC FE FF call _printf (012013C5h) 01213753 83 C4 10 add esp,10h
GetCReturn
164: // 对象作为返回值 165: 166: CReturn GetCReturn() 167: { 012078A0 55 push ebp 012078A1 8B EC mov ebp,esp 012078A3 81 EC 04 01 00 00 sub esp,104h 012078A9 53 push ebx 012078AA 56 push esi 012078AB 57 push edi 012078AC 8D BD FC FE FF FF lea edi,[ebp-104h] 012078B2 B9 41 00 00 00 mov ecx,41h 012078B7 B8 CC CC CC CC mov eax,0CCCCCCCCh 012078BC F3 AB rep stos dword ptr es:[edi] 012078BE A1 08 80 2C 01 mov eax,dword ptr [__security_cookie (012C8008h)] 012078C3 33 C5 xor eax,ebp 012078C5 89 45 FC mov dword ptr [ebp-4],eax //当前域对象计数 168: CReturn Return ; 169: Return.m_nNumber = 0; 012078C8 C7 45 CC 00 00 00 00 mov dword ptr [Return],0 170: for (int i = 0; i < 10; i++) 012078CF C7 45 C0 00 00 00 00 mov dword ptr [ebp-40h],0 012078D6 EB 09 jmp GetCReturn+41h (012078E1h) 012078D8 8B 45 C0 mov eax,dword ptr [ebp-40h] 012078DB 83 C0 01 add eax,1 012078DE 89 45 C0 mov dword ptr [ebp-40h],eax 012078E1 83 7D C0 0A cmp dword ptr [ebp-40h],0Ah 012078E5 7D 0F jge GetCReturn+56h (012078F6h) 171: { 172: Return.m_nArry[i] = i+1; 012078E7 8B 45 C0 mov eax,dword ptr [ebp-40h] 171: { 172: Return.m_nArry[i] = i+1; 012078EA 83 C0 01 add eax,1 012078ED 8B 4D C0 mov ecx,dword ptr [ebp-40h] 012078F0 89 44 8D D0 mov dword ptr [ebp+ecx*4-30h],eax 173: } 012078F4 EB E2 jmp GetCReturn+38h (012078D8h) 174: return Return; 012078F6 B9 0B 00 00 00 mov ecx,0Bh 012078FB 8D 75 CC lea esi,[Return] 012078FE 8B 7D 08 mov edi,dword ptr [ebp+8] 01207901 F3 A5 rep movs dword ptr es:[edi],dword ptr [esi] //将局部对象Return 复制到返回对象中 (如果有拷贝构造函数,此处调用) 01207903 8B 45 08 mov eax,dword ptr [ebp+8] 175: }