下面來看壹下執行過程
在主程序中每次調用函數時,先依次把各參數以相反的順序入棧;
然後call func_name, 這裏call要做兩件事: 壹是把函數的返回地址入棧,二是讓指令執行指針%eip指向函數開始處。
開始執行
現在函數要開始執行了,但它執行函數代碼前還要做壹點小事,首先把原來的基地址寄存器%ebp值入棧,因為在程序執行中%ebp要另作它用, 接著堆棧指針%esp的值復制給%ebp, 此後在函數執行中%ebp壹直保持不變,可以由此尋址獲得函數參數。
pushl %ebp
movl %esp, %ebp
下面開始執行函數代碼了。函數先要把它的局部變量保存在棧中,這很簡單。比如要保存壹個long型數據,只要把%esp指針向下移動4個字節(因為棧增長方向是由高地址到低地址),再根據%esp把該數據移入. 下面是保存兩個局部變量long後的堆棧內容:
Parameter #N <--- N*4+4(%ebp)
...
Parameter 2 <--- 12(%ebp)
Parameter 1 <--- 8(%ebp)
Return Address <--- 4(%ebp)
Old %ebp <--- (%ebp)
Local Variable 1 <--- -4(%ebp)
Local Variable 2 <--- -8(%ebp) and (%esp)
從上可以看出通過%ebp基地址尋址可以訪問所有的函數參數和局部變量. 當然也可以不用
%ebp而用其它的寄存器進行同樣的基地址尋址。但對於x86結構使用%ebp寄存器可能會更
快壹點。
執行結束: