亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解如何實現(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ù)目標虛函數(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做準備的。

在調(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是目標虛函數(shù)IsLoadFinish在虛函數(shù)中的偏移,所以對edx+78h地址取址,是讀出虛函數(shù)表該位置存放的就是目標虛函數(shù)IsLoadFinish的地址(代碼段地址),所以執(zhí)行這行代碼后,eax寄存器中存放的就是目標虛函數(shù)IsLoadFinish的地址,然后call eax就是調(diào)用虛函數(shù)IsLoadFinish了。

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

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

相關(guān)文章

  • 基于C/C++ 常見誤區(qū)詳解

    基于C/C++ 常見誤區(qū)詳解

    本篇文章介紹了在c和c++中一些常見誤區(qū)的詳細概述。需要的朋友參考下
    2013-05-05
  • 關(guān)于C語言 const 和 define 區(qū)別

    關(guān)于C語言 const 和 define 區(qū)別

    這篇文章主要介紹了關(guān)于C語言 const 和 define 區(qū)別 的相關(guān)資料,需要的朋友可以參考下面文章內(nèi)容
    2021-09-09
  • C++踩坑實戰(zhàn)之構(gòu)造和析構(gòu)函數(shù)

    C++踩坑實戰(zhàn)之構(gòu)造和析構(gòu)函數(shù)

    不論是構(gòu)造函數(shù),還是析構(gòu)函數(shù),都是C++、C#語言相對于其他語言而言特殊的地方,它是為了方便類中對象的初始化,這篇文章主要給大家介紹了關(guān)于C++踩坑實戰(zhàn)之構(gòu)造和析構(gòu)函數(shù)的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • C語言實現(xiàn)單詞小助手改進版

    C語言實現(xiàn)單詞小助手改進版

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)單詞小助手的改進版,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • C語言詳解實現(xiàn)鏈式二叉樹的遍歷與相關(guān)接口

    C語言詳解實現(xiàn)鏈式二叉樹的遍歷與相關(guān)接口

    二叉樹的鏈式存儲結(jié)構(gòu)是指,用鏈表來表示一棵二叉樹,即用鏈來指示元素的邏輯關(guān)系。通常的方法是鏈表中每個結(jié)點由三個域組成,數(shù)據(jù)域和左右指針域,左右指針分別用來給出該結(jié)點左孩子和右孩子所在的鏈結(jié)點的存儲地址
    2022-04-04
  • linux c多線程編程實例代碼

    linux c多線程編程實例代碼

    這篇文章主要介紹了linux系統(tǒng)中的c多線程編程實例,大家可以參考使用以下代碼
    2013-11-11
  • C語言實現(xiàn)萬年歷小功能

    C語言實現(xiàn)萬年歷小功能

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)萬年歷小功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • C++17之std::visit的具體使用

    C++17之std::visit的具體使用

    本文主要介紹了C++17之std::visit的具體使用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C/C++實現(xiàn)快速排序算法的兩種方式實例

    C/C++實現(xiàn)快速排序算法的兩種方式實例

    快速排序是一種采用分治思想,在實踐中通常運行較快一種排序算法,這篇文章主要給大家介紹了關(guān)于C/C++實現(xiàn)快速排序的兩種方式的相關(guān)資料,文中給出了詳細的示例代碼,需要的朋友可以參考下
    2021-08-08
  • C語言指針入門的簡單實例教程

    C語言指針入門的簡單實例教程

    這篇文章主要給大家介紹了關(guān)于C語言指針入門的簡單實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評論