最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解如何實現(xiàn)C++虛函數(shù)調(diào)用匯編代碼

 更新時間:2021年11月15日 11:19:50   作者:link-初揚  
多態(tài)是C++中最重要的特性之一,對虛函數(shù)的調(diào)用在C++代碼中是隨處可見的,本篇文章我們詳細探討一下,感興趣的朋友快來看看吧

虛函數(shù)(代碼段地址)被存放在虛函數(shù)表中,調(diào)用虛函數(shù)的流程是這樣子的:先獲取虛函數(shù)表的首地址,然后根據(jù)目標(biāo)虛函數(shù)在虛函數(shù)表的位置(offset偏移)取出虛函數(shù)表中的虛函數(shù)地址,最后去call這個虛函數(shù)(地址),就完成虛函數(shù)的調(diào)用。這個虛函數(shù)調(diào)用的流程在匯編代碼中可以最直觀的反映出來。

在排查軟件異?;虮罎r,我們時常要借助匯編代碼的上下文去輔助分析問題。讀懂C++虛函數(shù)調(diào)用的匯編代碼實現(xiàn),對于搞懂匯編代碼的上下文時很有好處的。今天我們就來看看虛函數(shù)調(diào)用的匯編代碼實現(xiàn)。

比如如下的C++代碼:

// 1、虛接口類中定義了純虛接口
class IContactInterface
{
    //...
 
    virtual BOOL IsLoadFinish() == 0;  // 虛接口
 
    //...
}
 
 
// 2、子類中實現(xiàn)虛接口
class Contact : public IContactInterface
{
    //...
 
    BOOL IsLoadFinish(); 
 
    //...
}
 
 
// 3、new出子類的對象,存放到父類的指針變量中
IContactInterface* g_pContactPtr = new Contact;
 
 
// 4、獲取子類對象的接口實現(xiàn)
IContactInterface* GetContactPtr()
{
    return g_pContactPtr;
} 
 
 
// 5、調(diào)用GetContactPtr獲取子類的對象去調(diào)用虛函數(shù)IsLoadFinish
GetContactPtr()->IsLoadFinish();

上述C++代碼片中,主要包含了以下幾點:

1)定義了虛接口類IContactInterface,在類中有個IsLoadFinish虛函數(shù);

2)定義了一個子類Contact,繼承于IContactInterface接口類,并實現(xiàn)了虛函數(shù)IsLoadFinish;

3)new出一個Contact類的對象,賦值給父類IContactInterface的指針變量;

4)調(diào)用GetContactPtr接口獲取IContactInterface指針變量,調(diào)用虛函數(shù)IsLoadFinish。

其中,GetContactPtr()->IsLoadFinish()這句虛函數(shù)調(diào)用的匯編代碼如下所示:

.text:005103EB call ds:__imp__GetContactPtr
.text:005103F1 mov [ebp+var_2AF4], eax
.text:005103F7 mov ecx, [ebp+var_2AF4]
.text:005103FD mov edx, [ecx]
.text:005103FF mov ecx, [ebp+var_2AF4]
.text:00510405 mov eax, [edx+78h]
.text:00510408 call eax

現(xiàn)在我們就來詳細解讀一下這段實現(xiàn)虛函數(shù)調(diào)用的匯編代碼。

1、匯編代碼段1:

.text:005103EB call ds:__imp__GetContactPtr
.text:005103F1 mov [ebp+var_2AF4], eax
.text:005103F7 mov ecx, [ebp+var_2AF4]

調(diào)用GetContactPtr接口,返回IContactInterface*指針,其中存放的是子類Contact對象。GetContactPtr接口返回的IContactInterface*指針中的值,放到eax寄存器中。

在C++的匯編代碼中,調(diào)用函數(shù)的返回值是放到eax寄存器中的。

所以eax中存放的是子類Contact對象的地址。然后將eax中存放的子類Contact對象的地址,放到函數(shù)棧內(nèi)存[ebp+var_2AF4]中。然后又將子類Contact對象的地址放到ecx寄存器中。

2、匯編代碼段2:

.text:005103FD mov edx, [ecx]

代碼運行至此,此時ecx中存放的就是子類Contact對象的地址。該句匯編代碼是以ecx中的值作為內(nèi)存地址,取出該地址中的值放到edx寄存器中。

在C++中,C++類中如果有虛函數(shù),則類中會掩藏一個虛函數(shù)指針成員變量,是排放在C++類所有數(shù)據(jù)成員的首位,所以C++對象的地址,就是虛函數(shù)表指針變量的內(nèi)存首地址(是指針變量的地址,不是指針變量中的值),所以此處的[ecx]操作,是取出虛函數(shù)表指針變量中存放的內(nèi)容,即虛函數(shù)表的首地址。所以edx寄存器中存放的是Contact對象中的虛函數(shù)表的首地址。

C++類中如果有虛函數(shù),則該類中會掩藏一個用來存放虛函數(shù)表地址的虛函數(shù)表指針變量,該虛函數(shù)表指針變量放置在該C++對象所有數(shù)據(jù)成員的首位,所以C++對象的地址就是其虛函數(shù)指針變量的內(nèi)存首地址。

3、匯編代碼段3:

.text:005103FF mov ecx, [ebp+var_2AF4]

回到整段匯編代碼最開始的地方,[ebp+var_2AF4]中存放的是子類Contact對象的地址。因為下面要調(diào)用Contact類對象的虛函數(shù),調(diào)用時要將Contact類對象的地址傳給被調(diào)用的函數(shù),即this指針。C++匯編代碼中,是通過ecx寄存器將類對象的地址傳給被調(diào)用函數(shù),所以此句代碼是為下面調(diào)用類Contact的虛函數(shù)IsLoadFinish做準(zhǔn)備的。

在調(diào)用C++類的函數(shù)時,是通過ecx寄存器傳遞C++類對象的地址的,即this指針的存放的C++對象的地址。

4、匯編代碼段4:

.text:00510405 mov eax, [edx+78h]
.text:00510408 call eax

接著上面,當(dāng)前edx寄存器中存放的值是虛函數(shù)表的首地址(虛函數(shù)表指針中存放的值),78h是目標(biāo)虛函數(shù)IsLoadFinish在虛函數(shù)中的偏移,所以對edx+78h地址取址,是讀出虛函數(shù)表該位置存放的就是目標(biāo)虛函數(shù)IsLoadFinish的地址(代碼段地址),所以執(zhí)行這行代碼后,eax寄存器中存放的就是目標(biāo)虛函數(shù)IsLoadFinish的地址,然后call eax就是調(diào)用虛函數(shù)IsLoadFinish了。

在C++中,函數(shù)名稱其實就是該函數(shù)在代碼段的首地址,去call這個首地址,就是去調(diào)用這個虛函數(shù)了。要注意區(qū)分?jǐn)?shù)據(jù)段地址和代碼段的地址。

到此這篇關(guān)于詳解如何實現(xiàn)C++虛函數(shù)調(diào)用匯編代碼的文章就介紹到這了,更多相關(guān)C++ 虛函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c++ 調(diào)用python傳輸圖片實例

    c++ 調(diào)用python傳輸圖片實例

    今天小編就為大家分享一篇c++ 調(diào)用python傳輸圖片實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • Opencv開發(fā)實現(xiàn)拼圖游戲

    Opencv開發(fā)實現(xiàn)拼圖游戲

    這篇文章主要為大家詳細介紹了Opencv開發(fā)實現(xiàn)拼圖游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • 深入Linux grep指令的詳解(實用型)

    深入Linux grep指令的詳解(實用型)

    本篇文章是對Linux下的grep指令進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C++函數(shù)對象詳解附帶實例

    C++函數(shù)對象詳解附帶實例

    這篇文章主要介紹了C++函數(shù)對象詳解附帶實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 關(guān)于Qt?C++中connect的幾種寫法代碼示例

    關(guān)于Qt?C++中connect的幾種寫法代碼示例

    這篇文章介紹了Qt中connect函數(shù)的不同編寫方式,包括傳統(tǒng)的槽函數(shù)寫法、使用函數(shù)指針的寫法、Lambda表達式以及使用QOverload選擇重載信號的寫法,每種寫法都有其特點和適用場景,程序員應(yīng)根據(jù)具體需求選擇最合適的方式,需要的朋友可以參考下
    2024-11-11
  • 用C++類實現(xiàn)單向鏈表的增刪查和反轉(zhuǎn)操作方法

    用C++類實現(xiàn)單向鏈表的增刪查和反轉(zhuǎn)操作方法

    下面小編就為大家?guī)硪黄肅++類實現(xiàn)單向鏈表的增刪查和反轉(zhuǎn)操作方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • C++鏈表類的封裝詳情介紹

    C++鏈表類的封裝詳情介紹

    這篇文章主要介紹了C++鏈表類的封裝,文章基于C++的相關(guān)資料展開主題的詳細內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-04-04
  • C語言新建臨時文件和臨時文件名的方法

    C語言新建臨時文件和臨時文件名的方法

    這篇文章主要介紹了C語言新建臨時文件和臨時文件名的方法,分別是mkstemp()函數(shù)和mktemp()函數(shù)的使用,需要的朋友可以參考下
    2015-08-08
  • 詳解C++?OpenCV實現(xiàn)圖像拼接的原理及方法

    詳解C++?OpenCV實現(xiàn)圖像拼接的原理及方法

    本文以實現(xiàn)圖像拼接為目標(biāo),把分割開的圖像進行拼接還原,核心的內(nèi)容包括:OpenCV圖像拼接相關(guān)原理以及OpenCV圖像拼接案例的實現(xiàn),感興趣的可以了解一下
    2022-07-07
  • 詳解如何利用C++實現(xiàn)一個反射類

    詳解如何利用C++實現(xiàn)一個反射類

    這篇文章主要為大家詳細介紹了如何利用C++實現(xiàn)一個反射類,文中的示例代碼講解詳細,具有一定的參考價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-03-03

最新評論

资中县| 平陆县| 卢龙县| 西和县| 友谊县| 洛扎县| 隆化县| 甘孜| 新巴尔虎左旗| 靖江市| 潼南县| 贵阳市| 上思县| 平乐县| 丹寨县| 疏勒县| 丁青县| 石门县| 高密市| 徐汇区| 会东县| 珠海市| 龙山县| 黄山市| 崇礼县| 衡南县| 陇南市| 建平县| 玉门市| 郁南县| 涿鹿县| 上犹县| 平安县| 吉安市| 西昌市| 博客| 怀集县| 宁夏| 深泽县| 河池市| 榆社县|