堆棧是C語言程序運行時必須的一個記錄調用路徑和參數的空間
????? -- 函數調用堆棧框架
????? -- 傳遞參數
????? -- 保存返回地址
????? -- 提供局部變量空間
* 函數的返回值默認使用 eax 寄存器存儲返回給上一級函數
了解堆棧存在的目的和編譯器對堆棧使用的規則是理解操作系統一些關鍵性代碼的基礎
堆棧寄存器
????? -- ebp 基址指針(base pointer),在C語言中用作記錄當前函數調用基址
????? -- esp 堆棧指針(stack pointer)
堆棧操作
????? -- push 棧頂地址減少4個字節(32位)
????? -- pop 棧頂地址增加4個字節(32位)
堆棧操作中涉及的其它關鍵寄存器
????? cs : eip? 總是指向下一條指令的地址
????? -- 順序執行:總是指向地址連續的下一條指令
????? -- 跳轉/分支:執行這樣的指令的時候,cs:eip的值會根據程序需要被修改
????? -- call:將當前cs:eip的值壓入棧頂,cs:eip指向被調用函數的入口地址
????? -- ret:從棧頂彈出原來保存在這里的cs:eip的值,放入cs:eip
????? -- 發生中斷時,CPU把寄存器的值壓到內核堆棧里,eip指向中斷處理程序的入口地址
Stack memory + operations
Stack grows down
Use to implement procedure calls
(* 號表示eip寄存器不能被直接修改,只能通過特殊指令間接修改)
函數調用堆棧框架
call target
????? -- 執行call之前
????? -- 執行call時,cs:eip原來的值指向call下一條指令,該值被保存到棧頂,然后cs:eip的值指向target的入口地址
進入target(Prologue)
????? -- 第一條指令:pushl %ebp
????? -- 第二條指令:movl %esp, %ebp
????? -- 函數體中的常規操作,可能會壓棧、出棧
退出target(Epilogue)
????? -- 第一條指令:movl %ebp, %esp
????? -- 第二條指令:popl %ebp
????? -- ret
Gcc calling conventions
Saved %ebp’s form a chain, can walk stack
Arguments and locals at fixed offsets from EBP
通過反匯編一個簡單的C程序,分析匯編代碼理解C語言函數調用堆棧框架
C程序
匯編代碼
觀察另一段小程序
觀察main中的局部變量
如何傳遞參數給p2
Q:p2的返回值是如何返回給main的?
觀察p2的堆棧框架
(完)