從這部分開始我們除了利用內(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文章
5295瀏覽量
119834 -
打印
+關(guān)注
關(guān)注
1文章
64瀏覽量
18683 -
編譯器
+關(guān)注
關(guān)注
1文章
1617瀏覽量
49016
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論