注銷

          注銷

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            112 隨筆 :: 7 文章 :: 18 評論 :: 0 Trackbacks

          為了搞清楚VC中類的實現專門寫了一個最簡單的類,用來觀察它的實現過程,代碼如下:
          // 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();
          }




          下面是相應的反匯編代碼:
          --- 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] //這是用來保存aTest的this指針,因為是局部變量所以是保存在[ebp-10h]中
          00401080  call    @ILT+30(CTest::CTest) (00401023) //調用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] //把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] //同樣是this指針
          004010A9  call    @ILT+25(CTest::~CTest) (0040101e) //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] //不要想這里的[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   //由于是STDCALLR所以棧是由程序自己來平衡的

          posted on 2006-11-19 10:14 注銷..... 閱讀(322) 評論(0)  編輯  收藏 所屬分類: c++
          主站蜘蛛池模板: 松溪县| 锦州市| 东乡族自治县| 泰安市| 图木舒克市| 肇庆市| 甘肃省| 都匀市| 徐闻县| 南昌县| 赞皇县| 钟山县| 黑龙江省| 邯郸县| 武穴市| 轮台县| 岳西县| 盐源县| 鄂伦春自治旗| 昌都县| 新民市| 内黄县| 云林县| 昆山市| 通许县| 玉门市| 临漳县| 通化市| 佳木斯市| 株洲县| 南澳县| 驻马店市| 定结县| 罗江县| 基隆市| 荔浦县| 府谷县| 全州县| 长岛县| 平定县| 泽普县|