函式調用匯編程式碼分析
c語言程式碼和彙編後的彙編程式碼分別如下圖所示:
在main函式中返回值f(2)+1,所以首先呼叫f(2)函式,在呼叫f(2)函式之前要先儲存main函式目前的狀態,棧基址指標,棧指標 之間的內容是main函式執行存放在棧中的內容,保護這兩個暫存器之間的內容可以保證返回main函式後可以使棧中的內容不被破壞。
pushl %ebp ,movl %esp,%ebp ,subl $4,%esp
以上兩條指令將ebp壓棧,將esp作為新的ebp,通過subl $4,%esp 將esp地址下移以為,在ebp之上重新構造一個新函式的棧空間,esp指向新的棧頂。
movl $2,(%esp) , call f
將f函式的引數2放入esp所指向的地址空間,傳入f函式中,跳轉到f中。
f:
pushl %ebp movl %esp ,%ebp subl $4,%esp movl 8(%ebp),%eax movl %eax,(%esp) call g
進入f函式後,由於要呼叫g函式,所以和在main函式中呼叫f函式相同,將ebp壓棧,esp作為新的棧低,重新構造一個堆疊,先將main函式中呼叫f函式傳送的引數取出送往eax中,然後將要傳入g函式的引數傳入(%esp) 中,然後跳轉到新的函式g中。
g:
pushl %ebp movl %esp,%ebp movl 8(%ebp),%eax addl $2,%eax popl %ebp ret
如前函式構造一個新的堆疊,將呼叫g函式傳送的引數取出送往eax中,完成函式呼叫後,還是將傳回的引數放在eax中,退出的在g函式所建立的堆疊,將之前壓入棧中的上一個堆疊的ebp彈出,恢復上一個堆疊,返回到上一層函式。
f:
leave ret
在f函式中無函式執行,傳回的引數仍然在eax中,保持不動,恢復上一級main函式的堆疊,返回上一級函式main()。
main:
addl $1,%eax leave ret
沿著被呼叫後的函式後執行,返回的引數仍然存放在eax中,執行完main函式中程式碼後,將所建立的堆疊退回之前的狀態。