潘凱 C 物件布局及多型實現的探索 五

2021-04-13 08:55:20 字數 2025 閱讀 6315

普通成員函式的呼叫

從這部分開始我們除了利用記憶體的資訊列印來進行探索外,更多的會通過跟蹤和觀察編譯器產生的彙編**來理解編譯器對這些語言特性的實現方式。彙編方面知識的討論超出了本文的範圍,我只對和我們討論相關的彙編**進行解析。理解本文要討論的知識並不需要有很完整的彙編知識,但必須了解起碼的概念。

下面我們看看引入虛繼承後的影響。為了有所對比我們首先看看普通成員函式的呼叫情況。

執行如下**,它包括了物件的普通成員函式呼叫,類的靜態成員函式呼叫、通過指標呼叫普通成員函式:

c010 obj;

print_obj_adr(obj)

obj.foo();

c012::sfoo();

c010 * pt = &obj;

pt->foo();

結果如下:

obj's address is : 0012f843

這是obj物件的記憶體位址。

首先我們看看物件的普通成員函式呼叫,obj.foo();,對應的彙編**為:

00422e09 lea ecx,[ebp+fffff967h]

00422e0f call 0041e289

第1行把物件的位址存入ecx暫存器,執行完這行指令後,我們要以看到ecx中的值為0x0012f843,就是前面列印出的值。如果函式需要傳遞引數,我們還會在前面看到一些push指令。在第2行我們可以看到call的是乙個直接的位址,這也就是靜態繫結。即函式的呼叫位址在編譯時已經被編譯器決議。

跟蹤進去我們要以看到是一條跳轉指令,繼續執行可以看到真正的函式**部分,如下(注:為了討論方便我在第行前面加了乙個行號):

01 00425fe0 push ebp

02 00425fe1 mov ebp,esp

03 00425fe3 sub esp,0cch

04 00425fe9 push ebx

05 00425fea push esi

06 00425feb push edi

07 00425fec push ecx

08 00425fed lea edi,[ebp+ffffff34h]

09 00425ff3 mov ecx,33h

10 00425ff8 mov eax,0cccccccch

11 00425ffd rep stos dword ptr [edi]

12 00425fff pop ecx

13 00426000 mov dword ptr [ebp-8],ecx

14 00426003 mov eax,dword ptr [ebp-8]

15 00426006 mov byte ptr [eax],2

16 00426009 pop edi

17 0042600a pop esi

18 0042600b pop ebx

19 0042600c mov esp,ebp

20 0042600e pop ebp

21 0042600f ret

我們看看第7行,把ecx暫存器入棧,後面4行初始化了函式的堆疊中的儲存區域性變數的部分。第12行彈出ecx值,到這裡時ecx的值保持為在函式呼叫前存入的物件記憶體位址,第13行就是儲存this指標的值,作為乙個區域性變數。這樣我們就知道了vc7.1不是象傳遞普通函式那樣通過壓棧來傳遞this指標,而是通過ecx暫存器來傳遞。第14、15行利用這個this指標給物件的成員變數進行了賦值。

再看看靜態成員函式呼叫的彙編**:

00422e14 call 0041dd84

非常直接,因為它不需要處理this指標,跟蹤到函式的彙編**,可以看到同樣不需要處理this指標。具體的**這裡就不列出來了。

再看看通過指標呼叫普通成員函式pt->foo();,產生的彙編**如下:

00422e25 mov ecx,dword ptr [ebp+fffff958h]

00422e2b call 0041e289

和通過物件呼叫普通成員函式的**差不多。不過存物件位址到ecx暫存器地,是通過解引用pt指標來找到物件位址的。

(未完待續)

潘凱 C 物件布局及多型實現的探索 二

帶虛函式的類的物件布局 1 如果類中存在虛函式時,情況會怎樣呢?我們知道當乙個類中有虛函式時,編譯器會為該類產生乙個虛函式表,並在它的每乙個物件中插入乙個指向該虛函式表的指標,通常這個指標是插在物件的起始位置。所謂的虛函式表實際就是乙個指標陣列,其中的指標指向真正的函式起始位址。我們來驗證一下,定義...

潘凱 C 物件布局及多型實現的探索 十三

中所定義類的簡單說明 c000 空類。c010 帶普通成員函式及 或變數的頂層類。c011 帶普通成員函式及 或變數的頂層類。c012 帶靜態成員函式及變數的頂層類。c013 從c010繼承的有成員變數及覆蓋父類普通成員函式的類。c014 從c011繼承的空類。c015 從c010,c011繼承的空...

C 物件布局及多型實現的探索

虛函式的類的物件布局 1 如果類中存在虛函式時,情況會怎樣呢?我們知道當乙個類中有虛函式時,編譯器會為該類產生乙個虛函式表,並在它的每乙個物件中插入乙個指向該虛函式表的指標,通常這個指標是插在物件的起始位置。所謂的虛函式表實際就是乙個指標陣列,其中的指標指向真正的函式起始位址。我們來驗證一下,定義乙...