• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            asm, c, c++ are my all
            -- Core In Computer
            posts - 139,  comments - 123,  trackbacks - 0
            用內聯匯編調虛函數, 理解VTABLE原理

            虛函數和動態綁定是C++面向對象編程的核心內容之一。要理解C++虛函數的調用本質,就不得不說VPTR和VTABLE。所有擁有虛函數的C++類的大小都比可看到的內容多至少4個字節(如果派生樹中存在多繼承,就可能多于4個字節),這多出來的4個字節就是VPTR,它位于每個實例的最前方。VPTR的內容就是一個unsigned int的地址,指向一個內存區域,而這個被指向的內存區域就是VTABLE,所謂虛函數地址表。每個擁有虛函數的類都擁有一張VTABLE,里面是一個函數指針數組,每4個字節為一個單位,指向虛函數的入口地址。C++在調用虛函數時,首先要通過這個類的實例內容看到VPTR,從而找到VTABLE,然后根據要調用的虛函數,取相應偏移地址的內容,從而把調用轉到這個位置。

            以下是我用VC內聯匯編編寫的一個手工模擬此過程的示例,通過例子中的代碼可以清楚的看出虛函數的調用過程。首先定義一個類,它有一個虛函數:


            class ?Class1
            {
            ?
            int
            ?i;
            public
            :
            ?Class1(
            int ?i)? {? this -> i? = ?i;?}

            ?
            virtual ? void ?Print( int ?a,? int ?b)? {?printf( " i=%d?a=%d?b=%d " ,?i,?a,?b);?}
            }
            ;

            如果取這個類的大小,可以看到結果是8而不是4。
            下面聲明這個類的一個實例,并取得其VTABLE中第一個元素的值:

            ?Class1 * ?pC? = ? new ?Class1( 1 );
            ?
            int ?addr? = ? * ( int * )( * ( int * )pC);

            注意取值的這一行運用了復雜的強制類型轉換。我把它拆開解釋一下。首先是取得對象pC的前四個字節的內容,只要把pC轉換成int*然后直接取值就行了:
            ?*(int*)pC

            下一步是把取得的這個值當作是一個指針,也就是再進行一次強制類型轉換:
            ?(int*)(*(int*)pC)

            最后取這個指針所指內存的內容,也就是VTABLE中第一個函數的地址了:
            ?*(int*)(*(int*)pC)

            取得這個地址以后,下面就用匯編代碼來調用這個地址所指的函數:

            ?__asm
            ?
            {
            ??mov?ecx,?pC;
            ??push?
            3
            ;
            ??push?
            2
            ;
            ??call?addr;
            ?}


            注意調用類的非靜態成員函數時需要先把對應實例的地址放到ECX寄存器中,也就是平常所說的“隱藏參數”了,然后為函數Print壓兩個參數進棧,根據運行的結果可以明顯看出來調用類成員函數時也是從右向左壓棧的,最后用call語句調用函數。不難發現調用類成員函數在參數個數確定時也是由被調用者負責彈棧,看來類成員函數也是可以聲明為參數個數可變的函數了。

            最后,執行程序,得到結果:
            i=1 a=2 b=3?

            posted on 2006-11-19 04:13 Jerry Cat 閱讀(2853) 評論(4)  編輯 收藏 引用

            FeedBack:
            # re: 用內聯匯編調虛函數, 理解VTABLE原理
            2006-11-19 08:16 | Aki
            "不難發現調用類成員函數時也是由被調用者負責彈棧,看來類成員函數是不能聲明為參數個數可變的函數了"

            可變個數參數函數跟壓棧有關系還是彈棧有關系?  回復  更多評論
              
            # re: 用內聯匯編調虛函數, 理解VTABLE原理
            2006-11-19 08:48 | Aki
            再請教一個問題:如果this -> i = i;不加this-> 結果編譯器也沒有給加:
            mov ecx, DWORD PTR _i$[ebp]
            mov DWORD PTR _i$[ebp], ecx
            這個是編譯器的規定么,不能自動給加上么:
            mov ecx, DWORD PTR _this$[ebp]
            mov edx, DWORD PTR _i$[ebp]
            mov DWORD PTR [ecx+4], edx
            多謝!!  回復  更多評論
              
            # re: 用內聯匯編調虛函數, 理解VTABLE原理
            2006-11-21 01:19 | Jerry Cat
            已改 - 類成員函數是可以聲明為參數個數可變的函數。
            thiscall是C++成員函數調用的缺省約定.
            (1). 參數從右向左入棧
            (2). 如果參數個數確定,this指針通過ecx傳遞給被調用者;如果參數個數不確定,this指針在所有參數壓棧后被壓入堆棧。
            (3). 對參數個數不定的,調用者清理堆棧,否則函數自己清理堆棧  回復  更多評論
              
            # re: 用內聯匯編調虛函數, 理解VTABLE原理
            2007-11-13 16:59 |
            好  回復  更多評論
              

            <2006年12月>
            262728293012
            3456789
            10111213141516
            17181920212223
            24252627282930
            31123456

            常用鏈接

            留言簿(7)

            隨筆檔案

            最新隨筆

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲欧美久久久久9999| 久久久无码精品亚洲日韩京东传媒 | 亚洲精品乱码久久久久久| 亚洲国产成人久久精品99| 久久夜色精品国产噜噜麻豆| 国产精品无码久久综合| 国产精品欧美久久久久无广告| 国内精品久久久久久久亚洲 | 999久久久无码国产精品| 久久精品中文字幕久久| 精品久久人人爽天天玩人人妻| 久久人人爽人人人人爽AV | AA级片免费看视频久久| 一本大道久久香蕉成人网| 久久99精品久久久久久久久久| 久久久久国产亚洲AV麻豆| 久久精品国产亚洲AV无码麻豆| 久久免费视频6| 精品国产福利久久久| 伊人色综合久久天天人手人婷| 狠狠综合久久综合中文88| 久久青青草原亚洲av无码app| 老司机午夜网站国内精品久久久久久久久 | 久久久青草久久久青草| 久久天天躁夜夜躁狠狠| 久久久久久久久久久免费精品 | 国内精品人妻无码久久久影院导航| 久久香蕉国产线看观看乱码| 中文精品久久久久人妻不卡| 久久中文精品无码中文字幕| 99久久精品免费国产大片| 久久超碰97人人做人人爱| 亚洲色大成网站www久久九| 亚洲国产成人久久综合碰| 精品国产乱码久久久久久浪潮| 狠狠色丁香婷婷久久综合不卡| 久久久久人妻精品一区| 久久亚洲精品成人av无码网站| 亚洲精品乱码久久久久久蜜桃图片| 亚洲欧洲中文日韩久久AV乱码| 亚洲乱码日产精品a级毛片久久|