注銷

          注銷

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            112 隨筆 :: 7 文章 :: 18 評(píng)論 :: 0 Trackbacks

          為了搞清楚VC中類的實(shí)現(xiàn)專門寫了一個(gè)最簡(jiǎn)單的類,用來(lái)觀察它的實(shí)現(xiàn)過(guò)程,代碼如下:
          // test.cpp : Defines the entry point for the console application.
          //

          #include "stdafx.h"
          #include "CTest.h"

          int main(int argc, char* argv[])
          {
          CTest aTest;
          aTest.a(1,2);
          return 0;
          }

          // CTest.h: interface for the CTest class.
          //
          //////////////////////////////////////////////////////////////////////

          #if !defined(AFX_CTEST_H__2CCCDCFC_6C3A_48BC_9CD0_E7A8E63431D9__INCLUDED_)
          #define AFX_CTEST_H__2CCCDCFC_6C3A_48BC_9CD0_E7A8E63431D9__INCLUDED_

          #if _MSC_VER > 1000
          #pragma once
          #endif // _MSC_VER > 1000

          class CTest 
          {
          public:
          CTest();
          virtual ~CTest();

          public:
          void b();
          void a(int one,int two);
          };

          #endif // !defined(AFX_CTEST_H__2CCCDCFC_6C3A_48BC_9CD0_E7A8E63431D9__INCLUDED_)


          // CTest.cpp: implementation of the CTest class.
          //
          //////////////////////////////////////////////////////////////////////

          #include "stdafx.h"
          #include "CTest.h"

          //////////////////////////////////////////////////////////////////////
          // Construction/Destruction
          //////////////////////////////////////////////////////////////////////

          CTest::CTest()
          {

          }

          CTest::~CTest()
          {

          }

          void CTest::b()
          {
          printf("b is be called by a");
          }

          void CTest::a(int one,int two)
          {
          printf("call b");
          b();
          }




          下面是相應(yīng)的反匯編代碼:
          --- D:\myown\test\test.cpp -----------------------------------------------------------------------------------------------
          1:  // test.cpp : Defines the entry point for the console application.
          2:  //
          3:
          4:  #include "stdafx.h"
          5:  #include "CTest.h"
          6:
          7:  int main(int argc, char* argv[])
          8:  {
          00401050  push    ebp
          00401051  mov     ebp,esp
          00401053  push    0FFh
          00401055  push    offset __ehhandler$_main (00410c89)
          0040105A  mov     eax,fs:[00000000]
          00401060  push    eax
          00401061  mov     dword ptr fs:[0],esp
          00401068  sub     esp,48h
          0040106B  push    ebx
          0040106C  push    esi
          0040106D  push    edi
          0040106E  lea     edi,[ebp-54h]
          00401071  mov     ecx,12h
          00401076  mov     eax,0CCCCCCCCh
          0040107B  rep stos  dword ptr [edi]

          9:    CTest aTest;
          0040107D  lea     ecx,[ebp-10h] //這是用來(lái)保存aTest的this指針,因?yàn)槭蔷植孔兞克允潜4嬖赱ebp-10h]中
          00401080  call    @ILT+30(CTest::CTest) (00401023) //調(diào)用aTest的構(gòu)造函數(shù),由編譯器自動(dòng)產(chǎn)生的CALL
          00401085  mov     dword ptr [ebp-4],0

          10:    aTest.a(1,2);
          0040108C  push    2
          0040108E  push    1
          00401090  lea     ecx,[ebp-10h] //把a(bǔ)Test的this指針用ecx進(jìn)行傳遞
          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] //同樣是this指針
          004010A9  call    @ILT+25(CTest::~CTest) (0040101e) //aTest的生存周期到了,自動(dòng)調(diào)用析構(gòu)函數(shù),同樣是由編譯器分析之后自加上去
          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

          下面再來(lái)分析一下VC中對(duì)函數(shù)的調(diào)用:
          可以看到上面有對(duì)三個(gè)函數(shù)的調(diào)用分別為:
          00401080  call    @ILT+30(CTest::CTest) (00401023)
          00401093  call    @ILT+5(CTest::a) (0040100a)
          004010A9  call    @ILT+25(CTest::~CTest) (0040101e)

          可以看到他們都跳到了以@ILT為基的一個(gè)地址去了,那么跳過(guò)去之后可以看到:
          @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)

          這個(gè)@ILT其實(shí)就是一個(gè)靜態(tài)的表,它記錄了一些函數(shù)的入口然后跳過(guò)去,每個(gè)跳轉(zhuǎn)jmp占一個(gè)字節(jié),然后就是一個(gè)四字節(jié)的內(nèi)存地址,所以加起為五個(gè)字節(jié),這樣就實(shí)現(xiàn)了類的機(jī)制。

          下面再來(lái)分析一下,類的成員函數(shù)調(diào)用另一成員函數(shù)的情況:

          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] //不要想這里的[ebp-4]肯定是this指針,
          0040125D  call    @ILT+15(CTest::b) (00401014) // 又是@ILT靜態(tài)表格
          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   //由于是STDCALLR所以棧是由程序自己來(lái)平衡的

          posted on 2006-11-19 10:14 注銷..... 閱讀(322) 評(píng)論(0)  編輯  收藏 所屬分類: c++
          主站蜘蛛池模板: 错那县| 太湖县| 漳平市| 察隅县| 定边县| 南城县| 平凉市| 和政县| 维西| 石河子市| 金平| 石楼县| 河北区| 日喀则市| 永城市| 和龙市| 青河县| 荔浦县| 深州市| 成武县| 闵行区| 新营市| 瑞昌市| 南郑县| 响水县| 楚雄市| 高雄县| 兴化市| 泗水县| 横山县| 翼城县| 大丰市| 确山县| 渝中区| 潼南县| 儋州市| 商水县| 上饶市| 武安市| 新乐市| 武威市|