Linux 函數調用棧的使用

結論:

1.esp指向棧頂存有數據的那個單元(而不是下一個單元)

2.在函數中臨時變量是存在棧頂和棧底之間的,包括參數在內。通常我們說通過棧傳遞參數,參數入棧的操作並不是push,而是movl 參數 0xXX(%esp)。

3.call函數時。返回地址保存到棧頂。是使用push指令的,會修改esp的值(-4

4.在被調用函數的開頭push ebp。保存原來棧底,也要修改esp的值(-4)。新的ebp指向存放老的ebp的位置。然後,利用add size esp爲被調用函數開闢棧空間。

5.在被調用函數中,取傳遞來的參數也是通過mov 0xXX(%ebp) 實現。




圖 1


例子程序反彙編代碼:

1.看int i=5,j=6;的彙編碼

使用的是%esp+0x14.這個位置是在ebp和esp之間

2.使用棧傳遞參數.在sum = add(i,j)下面四行

(1)從j所在位置取出值,存入eax中,mov 0x18(%esp),%eax  //可知,先是最右邊的參數

(2)將eax中的值放入棧頂的前一個位置,因爲只有兩個參數,所以右邊的參數放在棧頂前一個位置即可,如果是三個參數,就再往前放一個位置。

(3)同(1),取出j所在位置存放的值

(4)將該值放到棧頂單元。



圖2 


3.在被調用函數中取參數:

這是對被調用函數的單步調試,i是參數.執行li = i時.我們看到執行了兩條彙編語句:mov 0x8(%ebp),%eax 和 mov %eax,-08(%ebp).

從圖2中我們看到,i是函數調用中的第一個參數。根據參數調用時的順序,最左邊的參數最後入棧。然後是返回地址,再之後是保存舊的ebp的值。之後,新的ebp指向保存舊的ebp值的那個位置。見圖1.所以新的ebp+8就是取得了第一個參數。同理,新的ebp+0xc就是取得了第二個參數。取來之後,通過eax把它放到li所表示的位置中。完成參數傳遞,賦值到被調用函數中的局部變量中。



圖3





發佈了38 篇原創文章 · 獲贊 9 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章