C的function call與stack frame心得
為什么80%的碼農都做不了架構師?>>> ??
[技術] C的function call與stack frame心得
Written on 12:00 上午 by Yu Lai
從大二的Program Language中學到stack對於C的function call的實做與功用的概念,
以及各個register的功用,但從未實際地深入了解其中register的變化.
剛好最近T40灌了Ubuntu Linux (x86),就直接寫了些C code,
配合objdump與gdb來trace其中register的變化,於是有了這篇的心得.
首先是複習一下register:
%eip:instruction pointer,用來指到下一個instruction的位置.
%esp:stack pointer,用來指到目前stack的top.
%ebp:Frame pointer,用來指到目前stack frame的開頭.
這次所使用的source code:
我們先透過$ gcc -o test test.c編出test,
然後再透過objdump -d test來觀察disassemble出來的部份:
從0x0804835d開始,我們可以看到main()在呼叫hi()時的步驟,
首先先把ebp的值塞進stack中,然後把esp的值塞到ebp裡.
接著把esp減8(因為stack是由高位往低位),再分別把0x2和0x1塞入stack中,
這2個其實就是把hi()所需的變數放入stack中,最後就是call 8048344 <hi>.
接著透過gdb設好breakpoint把stack中的值給印出來.
從stack內的值我們可以觀察到,其實call指令所做的動作就是把下一筆instruction的
address(eip)給push進stack裡(0x08048378被放入0xbfb9a088中),接著再把call的address
塞到eip再執行它.
接著到了hi()中,和main()一樣的先把ebp塞入stack中,然後把把esp的值塞到ebp裡.
從這裡我們可以知道,一個function開始時,會先把上一個function的ebp放入stack中,
接著馬上設定自己的ebp.從這裡可以用來確保目前所在function的ebp的值的正確性,
以及保存之後要return時上一個function的ebp的值.
在hi()中把ebp設定好後,它先在stack中allocate了16個byte來使用,接著我們看到了
在ebp-4的位置上被填入了0x3的值,也就是我們在程式中宣告的變數int i = 3;的實做.
最後是leave指令和ret指令所實做出來的return;.在這裡leave指令的操作相當於
把ebp的值放到esp中,然後從stack中pop出值來放到ebp裡,而ret指令的操作則相當於從
stack中pop出值來放到eip裡.也就是說除了eip外,esp和ebp都回到呼叫hi()之前的狀況.
完成hi()的呼叫.
另外,如果hi()有值需要被return時,通常會透過eax register來傳遞.
也就是說在$lt;hi>中的leave指令前會加入mov xxx,%eax指令,
在<main>中call <hi>指令的下一個指令會是mov %eax,yyy指令讀出eax放入yyy中
和mov $0x0,%eax指令把eax清空.
以上就是我從gdb與objdump中所觀察到的一個C的function被呼叫的過程.
如內容有所錯誤,煩請有看到的人不吝賜教.Thanks.
轉載于:https://my.oschina.net/tsh/blog/1613642
總結
以上是生活随笔為你收集整理的C的function call與stack frame心得的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 椰子皮怎么去掉 椰子肉褐色的皮能吃吗
- 下一篇: js创建一个含有数字字母的随机字符串