從這部分開(kāi)始我們除了利用內(nèi)存的信息打印來(lái)進(jìn)行探索外,更多的會(huì)通過(guò)跟蹤和觀察編譯器產(chǎn)生的匯編代碼來(lái)理解編譯器對(duì)這些語(yǔ)言特性的實(shí)現(xiàn)方式。匯編方面知識(shí)的討論超出了本文的范圍,我只對(duì)和我們討論相關(guān)的匯編代碼進(jìn)行解析。理解本文要討論的知識(shí)并不需要有很完整的匯編知識(shí),但必須了解起碼的概念。
下面我們看看引入虛繼承后的影響。為了有所對(duì)比我們首先看看普通成員函數(shù)的調(diào)用情況。
執(zhí)行如下代碼,它包括了對(duì)象的普通成員函數(shù)調(diào)用,類的靜態(tài)成員函數(shù)調(diào)用、通過(guò)指針調(diào)用普通成員函數(shù):
結(jié)果如下:
這是obj對(duì)象的內(nèi)存地址。
首先我們看看對(duì)象的普通成員函數(shù)調(diào)用,obj.foo();,對(duì)應(yīng)的匯編代碼為:
第1行把對(duì)象的地址存入ecx寄存器,執(zhí)行完這行指令后,我們要以看到ecx中的值為0x0012F843,就是前面打印出的值。如果函數(shù)需要傳遞參數(shù),我們還會(huì)在前面看到一些push指令。在第2行我們可以看到call的是一個(gè)直接的地址,這也就是靜態(tài)綁定。即函數(shù)的調(diào)用地址在編譯時(shí)已經(jīng)被編譯器決議。
跟蹤進(jìn)去我們要以看到是一條跳轉(zhuǎn)指令,繼續(xù)執(zhí)行可以看到真正的函數(shù)代碼部分,如下(注:為了討論方便我在第行前面加了一個(gè)行號(hào)):
我們看看第7行,把ecx寄存器入棧,后面4行初始化了函數(shù)的堆棧中的保存局部變量的部分。第12行彈出ecx值,到這里時(shí)ecx的值保持為在函數(shù)調(diào)用前存入的對(duì)象內(nèi)存地址,第13行就是保存this指針的值,作為一個(gè)局部變量。這樣我們就知道了VC7.1不是象傳遞普通函數(shù)那樣通過(guò)壓棧來(lái)傳遞this 指針,而是通過(guò)ecx寄存器來(lái)傳遞。第14、15行利用這個(gè)this指針給對(duì)象的成員變量進(jìn)行了賦值。
再看看靜態(tài)成員函數(shù)調(diào)用的匯編代碼:
非常直接,因?yàn)樗恍枰幚韙his指針,跟蹤到函數(shù)的匯編代碼,可以看到同樣不需要處理this指針。具體的代碼這里就不列出來(lái)了。
再看看通過(guò)指針調(diào)用普通成員函數(shù)pt-》 foo();,產(chǎn)生的匯編代碼如下:
和通過(guò)對(duì)象調(diào)用普通成員函數(shù)的代碼差不多。不過(guò)存對(duì)象地址到ecx寄存器地,是通過(guò)解引用pt指針來(lái)找到對(duì)象地址的。
-
寄存器
+關(guān)注
關(guān)注
31文章
5427瀏覽量
123716 -
打印
+關(guān)注
關(guān)注
1文章
66瀏覽量
18972 -
編譯器
+關(guān)注
關(guān)注
1文章
1657瀏覽量
49976
發(fā)布評(píng)論請(qǐng)先 登錄
蓄電池在充放電時(shí)AD采樣到的值虛高虛低,怎樣解決?
C++ 多繼承類 虛基類分享
什么是繼承?
虛電路,虛電路的特點(diǎn),虛電路的原理是什么?
虛短和虛斷概念剖解及應(yīng)用實(shí)例
手機(jī)該不該ROOT權(quán)限?ROOT之后會(huì)怎樣?
PCBA加工中造成虛焊的原因及解決方法
一文詳解虛函數(shù)及其相關(guān)知識(shí)點(diǎn)
怎樣在Java中實(shí)現(xiàn)多繼承
什么是虛焊假焊?造成虛焊假焊的原因有哪些?
為什么運(yùn)放會(huì)有虛短虛斷?
造成虛焊、假焊的原因有哪些?如何預(yù)防虛焊假焊

評(píng)論