在函式呼叫的過程我們可以看作是乙個呼叫鏈。
例如:在main函式中呼叫sum函式,其中main為呼叫方,sum為被呼叫方
問題一:被呼叫方執行完後,怎麼回退到呼叫方函式???
問題二:被呼叫方函式執行完回到呼叫方函式後,怎麼知道延下一行繼續執行??
問題三:返回值是由什麼帶出來的??
問題四:形參需不需要開闢記憶體?如果形參開闢記憶體,在**開闢的?
2、在虛擬位址空間有一塊區域,稱為棧區,它是所有函式的活動區域。
而棧區是由棧幀組成的,棧幀是每乙個函式的活動區域。
3、知道棧後,想要解決上面的問題還需要通過在底層通過反彙編看每一天指令的執行。
彙編分為(1)linux下的at&t(2)windows下的inter x86
兩者的區別舉例說明:int a = 10;
在linux下彙編的指令是mov 0a , dword ptr[a]
,
在windows下彙編的指令是mov dword ptr[a] , 0a
則除操作碼以外,linux下是從左往右看。windows下是從右往左看。
(1)用來儲存資料的暫存器:eax 、ebx、ecx、edx
(2)棧底指標暫存器:ebp;棧頂指標暫存器:esp
棧頂指標暫存器和棧底指標暫存器共同標識乙個棧幀。
(3)pc下一行指令暫存器
(1)mov 移值指令
a =20;
反彙編:mov dwoad ptr[a],14
//表示把20放在a的位址下,放4個位元組
lea ebp , esp
//讓ebp、esp指向同乙個位置
(3)push 壓棧
push 0a
//將10壓到棧頂,同時esp = esp - 4(位元組對齊)
(4)pop 出棧
pop eax
//棧頂的值出棧後,將值存放在eax暫存器中
(5)add 加等指令
add eax,
10//eax+=10
(6)sub 減等指令
sub eax,
10//eax -= 10
#include
intsum
(int left,
int right)
intmain()
(1)先開始main函式
call指令就是將下一行指令壓棧,這樣就解決了問題一。
(2)在call指令後,我們進入了sum函式,任何函式在進行前都會進行下面一堆指令,我們用sum函式舉例,
每個函式進行前的這段指令的作用是:
①把棧幀轉換到被呼叫方
②給sum函式活動開闢空間
③給空間初始化為cccc cccc
(3)最後每次函式結束時都會進行清棧
①pop指令將在棧頂的暫存器edi、esi、ebx出棧,保證了在整個函式呼叫過程中,三個暫存器中的數值不會發生變化。
②mov esp,ebp是將esp指向ebp,將上面的記憶體空間歸還給系統。
③最後將棧底指標暫存器出棧。
開篇我們提出了三個問題,現在來總結一下
(1)問題一:被呼叫方執行完後,怎麼回退到呼叫方函式???
當呼叫函式時,將主程式**行的下一條指令的位址儲存到棧中(也就是7(1)中的call指令所做的事);當函式返回時,程式就會從棧中獲取該位址,並從那一位址位置繼續向下執行。
(2)問題二:被呼叫方函式執行完回到呼叫方函式後,怎麼知道延下一行繼續執行??
函式執行完後,緊接著把sum函式棧頂的三個暫存器出棧了(也就是清棧部分上面的三個pop)。然後mov esp,ebp ,這條指令將esp指向的位址指向了ebp指向的位址。即這條指令將開始進入函式時開闢的一些記憶體「清理」掉了。接下來 pop ebp ,將當前棧頂的資料出棧並賦給ebp。則當前棧頂的資料,即main函式的棧底位址。也就是sum函式呼叫完成後能返回到main函式棧幀上來。最後執行ret 指令,該過程執行了pop指令,將當前棧頂的資料出棧並賦給下一行指令暫存器。則當前棧底資料是main函式呼叫sum函式的call指令的下一條指令位址。也就是add esp,8 這條指令的位址0040109a.回到main函式後就可以接著下一條指令繼續執行了。
(3)問題三:返回值是由什麼帶出來的??
返回值返回時是把值賦給暫存器,再由暫存器帶回main函式,在函式非類型別(非c++)的返回值規則中:(1)4個位元組的返回值,由eax暫存器帶出來。(2)8個位元組的返回值由eax和edx暫存器帶出來。(3)大於8個位元組,是由臨時量帶出來的,返回值返回的是臨時量的位址。
(4)問題四:形參需不需要開闢記憶體?如果形參開闢記憶體,在**開闢的?
實參中的值從記憶體塊中取出來賦到暫存器中,然後暫存器再壓棧完成後,再去呼叫相應呼叫約定,如call跳轉到sum函式棧幀中,然後就開闢記憶體,是在呼叫方開闢,呼叫方清理的。
C 虛函式呼叫的反彙編解析
虛函式的呼叫如何能實現其 虛 作為c 多型的表現手段,估計很多人對其實現機制感興趣。大約一般的教科書就說到這個c 強大機制的時候,就是教大家怎麼用,何時用,而不會去 一下這個虛函式的真正實現細節。當然,因為不同的編譯器廠家,可能對虛函式有自己的實現,呵呵,這就算是虛函式對於編譯器的 多型 了 作為編...
C 虛函式呼叫的反彙編解析
虛函式的呼叫如何能實現其 虛 作為c 多型的表現手段,估計很多人對其實現機制感興趣。大約一般的教科書就說到這個c 強大機制的時候,就是教大家怎麼用,何時用,而不會去 一下這個虛函式的真正實現細節。當然,因為不同的編譯器廠家,可能對虛函式有自己的實現,呵呵,這就算是虛函式對於編譯器的 多型 了 作為編...
C 虛函式呼叫的反彙編解析
c 虛函式呼叫的反彙編解析 虛函式的呼叫如何能實現其 虛 作為c 多型的表現手段,估計很多人對其實現機制感興趣。大約一般的教科書就說到這個c 強大機制的時候,就是教大家怎麼用,何時用,而不會去 一下這個虛函式的真正實現細節。當然,因為不同的編譯器廠家,可能對虛函式有自己的實現,呵呵,這就算是虛函式對...