0040107D lea ecx,[ebp-10h] file://这是用来保存aTest的this指针,因为是局部变量所以是保存在[ebp-10h]中
00401080 call @ILT+30(CTest::CTest) (00401023) file://调用aTest的构造函数,由编译器自动产生的CALL
00401085 mov dword ptr [ebp-4],0
10: aTest.a(1,2);
0040108C push 2
0040108E push 1
00401090 lea ecx,[ebp-10h] file://把aTest的this指针用ecx进行传递
00401093 call @ILT+5(CTest::a) (0040100a)
11: return 0;
00401098 mov dword ptr [ebp-14h],0
0040109F mov dword ptr [ebp-4],0FFFFFFFFh
004010A6 lea ecx,[ebp-10h] file://同样是this指针
004010A9 call @ILT+25(CTest::~CTest) (0040101e) file://aTest的生存周期到了,自动调用析构函数,同样是由编译器分析之后自加上去
004010AE mov eax,dword ptr [ebp-14h]
12: }
004010B1 mov ecx,dword ptr [ebp-0Ch]
004010B4 mov dword ptr fs:[0],ecx
004010BB pop edi
004010BC pop esi
004010BD pop ebx
004010BE add esp,54h
004010C1 cmp ebp,esp
004010C3 call __chkesp (00401670)
004010C8 mov esp,ebp
004010CA pop ebp
004010CB ret
下面再来分析一下VC中对函数的调用:
可以看到上面有对三个函数的调用分别为:
00401080 call @ILT+30(CTest::CTest) (00401023)
00401093 call @ILT+5(CTest::a) (0040100a)
004010A9 call @ILT+25(CTest::~CTest) (0040101e)
可以看到他们都跳到了以@ILT为基的一个地址去了,那么跳过去之后可以看到:
@ILT+0( _GCTest@@UAEPAXI@Z):
00401005 jmp CTest::`scalar deleting destructor (00401130)
@ILT+5( a@CTest@@QAEXHH@Z):
0040100A jmp CTest::a (00401230)
@ILT+10(_main):
0040100F jmp main (00401050)
@ILT+15( b@CTest@@QAEXXZ):
00401014 jmp CTest::b (004011e0)
@ILT+20( _GCTest@@UAEPAXI@Z):
00401019 jmp CTest::`scalar deleting destructor (00401130)
@ILT+25( 1CTest@@UAE@XZ):
0040101E jmp CTest::~CTest (004011a0)
@ILT+30( 0CTest@@QAE@XZ):
00401023 jmp CTest::CTest (004010f0)
这个@ILT其实就是一个静态的表,它记录了一些函数的入口然后跳过去,每个跳转jmp占一个字节,然后就是一个四字节的内存地址,所以加起为五个字节,这样就实现了类的机制。
下面再来分析一下,类的成员函数调用另一成员函数的情况:
27: void CTest::a(int one,int two)
28: {
00401230 push ebp
00401231 mov ebp,esp
00401233 sub esp,44h
00401236 push ebx
00401237 push esi
00401238 push edi
00401239 push ecx
0040123A lea edi,[ebp-44h]
0040123D mov ecx,11h
00401242 mov eax,0CCCCCCCCh
00401247 rep stos dword ptr [edi]
00401249 pop ecx
0040124A mov dword ptr [ebp-4],ecx
29: printf("call b");
0040124D push offset string "call b" (00422038)
00401252 call printf (00401830)
00401257 add esp,4
30: b();
0040125A mov ecx,dword ptr [ebp-4] file://不要想这里的[ebp-4]肯定是this指针,
0040125D call @ILT+15(CTest::b) (00401014) // 又是@ILT静态表格
31: }
00401262 pop edi
00401263 pop esi
00401264 pop ebx
00401265 add esp,44h
00401268 cmp ebp,esp
0040126A call __chkesp (00401670)
0040126F mov esp,ebp
00401271 pop ebp
00401272 ret 8 file://由于是STDCALLR所以栈是由程序自己来平衡的