• <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
            用內(nèi)聯(lián)匯編調(diào)虛函數(shù), 理解VTABLE原理

            虛函數(shù)和動(dòng)態(tài)綁定是C++面向?qū)ο缶幊痰暮诵膬?nèi)容之一。要理解C++虛函數(shù)的調(diào)用本質(zhì),就不得不說(shuō)VPTR和VTABLE。所有擁有虛函數(shù)的C++類的大小都比可看到的內(nèi)容多至少4個(gè)字節(jié)(如果派生樹(shù)中存在多繼承,就可能多于4個(gè)字節(jié)),這多出來(lái)的4個(gè)字節(jié)就是VPTR,它位于每個(gè)實(shí)例的最前方。VPTR的內(nèi)容就是一個(gè)unsigned int的地址,指向一個(gè)內(nèi)存區(qū)域,而這個(gè)被指向的內(nèi)存區(qū)域就是VTABLE,所謂虛函數(shù)地址表。每個(gè)擁有虛函數(shù)的類都擁有一張VTABLE,里面是一個(gè)函數(shù)指針數(shù)組,每4個(gè)字節(jié)為一個(gè)單位,指向虛函數(shù)的入口地址。C++在調(diào)用虛函數(shù)時(shí),首先要通過(guò)這個(gè)類的實(shí)例內(nèi)容看到VPTR,從而找到VTABLE,然后根據(jù)要調(diào)用的虛函數(shù),取相應(yīng)偏移地址的內(nèi)容,從而把調(diào)用轉(zhuǎn)到這個(gè)位置。

            以下是我用VC內(nèi)聯(lián)匯編編寫(xiě)的一個(gè)手工模擬此過(guò)程的示例,通過(guò)例子中的代碼可以清楚的看出虛函數(shù)的調(diào)用過(guò)程。首先定義一個(gè)類,它有一個(gè)虛函數(shù):


            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);?}
            }
            ;

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

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

            注意取值的這一行運(yùn)用了復(fù)雜的強(qiáng)制類型轉(zhuǎn)換。我把它拆開(kāi)解釋一下。首先是取得對(duì)象pC的前四個(gè)字節(jié)的內(nèi)容,只要把pC轉(zhuǎn)換成int*然后直接取值就行了:
            ?*(int*)pC

            下一步是把取得的這個(gè)值當(dāng)作是一個(gè)指針,也就是再進(jìn)行一次強(qiáng)制類型轉(zhuǎn)換:
            ?(int*)(*(int*)pC)

            最后取這個(gè)指針?biāo)竷?nèi)存的內(nèi)容,也就是VTABLE中第一個(gè)函數(shù)的地址了:
            ?*(int*)(*(int*)pC)

            取得這個(gè)地址以后,下面就用匯編代碼來(lái)調(diào)用這個(gè)地址所指的函數(shù):

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


            注意調(diào)用類的非靜態(tài)成員函數(shù)時(shí)需要先把對(duì)應(yīng)實(shí)例的地址放到ECX寄存器中,也就是平常所說(shuō)的“隱藏參數(shù)”了,然后為函數(shù)Print壓兩個(gè)參數(shù)進(jìn)棧,根據(jù)運(yùn)行的結(jié)果可以明顯看出來(lái)調(diào)用類成員函數(shù)時(shí)也是從右向左壓棧的,最后用call語(yǔ)句調(diào)用函數(shù)。不難發(fā)現(xiàn)調(diào)用類成員函數(shù)在參數(shù)個(gè)數(shù)確定時(shí)也是由被調(diào)用者負(fù)責(zé)彈棧,看來(lái)類成員函數(shù)也是可以聲明為參數(shù)個(gè)數(shù)可變的函數(shù)了。

            最后,執(zhí)行程序,得到結(jié)果:
            i=1 a=2 b=3?

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

            FeedBack:
            # re: 用內(nèi)聯(lián)匯編調(diào)虛函數(shù), 理解VTABLE原理
            2006-11-19 08:16 | Aki
            "不難發(fā)現(xiàn)調(diào)用類成員函數(shù)時(shí)也是由被調(diào)用者負(fù)責(zé)彈棧,看來(lái)類成員函數(shù)是不能聲明為參數(shù)個(gè)數(shù)可變的函數(shù)了"

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

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理



            <2006年11月>
            2930311234
            567891011
            12131415161718
            19202122232425
            262728293012
            3456789

            常用鏈接

            留言簿(7)

            隨筆檔案

            最新隨筆

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            亚洲午夜无码久久久久| 国产巨作麻豆欧美亚洲综合久久| 日本三级久久网| 国产成人无码久久久精品一| 久久久这里只有精品加勒比| 理论片午午伦夜理片久久| 久久www免费人成看国产片| 日本免费一区二区久久人人澡| 久久国产精品久久久| 色综合久久久久网| 国产成人精品久久亚洲高清不卡 | 国产成人久久精品激情| 久久99毛片免费观看不卡| av无码久久久久久不卡网站 | 国产成人精品久久二区二区| 国产成人久久AV免费| 久久这里只精品国产99热| 伊人丁香狠狠色综合久久| 国产毛片久久久久久国产毛片| 久久精品亚洲男人的天堂| 人妻无码精品久久亚瑟影视 | 久久久久久一区国产精品| 无码乱码观看精品久久| 中文国产成人精品久久不卡| 精品蜜臀久久久久99网站| 97热久久免费频精品99| 久久er国产精品免费观看8| 久久99九九国产免费看小说| 久久国产精品99精品国产| 国产成人精品久久亚洲高清不卡 | 久久久久久久国产免费看| 久久久www免费人成精品| 欧美黑人又粗又大久久久| 伊人久久综在合线亚洲2019| 午夜精品久久影院蜜桃 | 亚洲中文字幕久久精品无码喷水| 狠狠色丁香婷综合久久| 久久精品国产男包| 好属妞这里只有精品久久| 精品综合久久久久久97| 国产午夜电影久久|