堆栈是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的堆栈框架
(完)