栈帧(Stack Frame)

0x01.栈在计算机中的应用

  • 在计算机系统中,栈也可以称之为栈内存是一个具有动态内存区域,存储函数内部(包括main函数)的局部变量和方法调用和函数参数值,是由系统自动分配的,一般速度较快;存储地址是连续且存在有限栈容量,会出现溢出现象,程序可以将数据压入栈中,也可以将数据从栈顶弹出。压栈操作使得栈增大,而弹出操作使栈减小。
  • 栈用于维护函数调用的上下文,离开了栈,函数调用就没法实现。
  • 栈是从高地址向低地址延伸。

0x02.栈帧和栈帧的结构

每一次函数的调用,都会在调用栈(call stack)上维护一个独立的栈帧(stack frame)。

一个函数的栈帧用ebp 和 esp 这两个寄存器来划定范围。

栈帧包括:

  1. 函数的返回地址和参数。
  2. 临时变量。 包括函数的非静态局部变量以及编译器自动生成的其他临时变量。
  3. 栈帧状态值:ebp (帧指针),指向当前的栈帧的底部;esp(栈指针) 始终指向栈帧的顶部;

栈帧从低到上依次是(从高地址到低地址的方向):

  1. 参数
  2. 返回地址
  3. ebp
  4. 局部变量
  5. esp

0x03.函数的调用过程

调用约定:

  •  函数调用约定描述了函数传递参数方式和栈帧同工作的技术细节。不同的操作系统、不同的语言、不同的编译器在实现函数调用时的原理虽然基本相同,但具体的调用约定还是有差别的。这包括参数传递方式,参数入栈顺序是从右向左还是从左向右,函数返回时恢复堆栈平衡的操作在子函数中进行还是在母函数中进行。
  • 同一段代码用不同的编译选项、不同的编译器编译链接后,得到的可执行文件会有很多不同。

调用过程:

  1. 参数入栈。将参数按照一定的顺序入栈。
  2. 返回地址入栈。将当前代码区调用指令的下一条指令地址压入栈中,供函数返回时继续执行。
  3. 代码区跳转。处理器从当前代码区跳转到被调用函数的入口处。
  4. 栈帧处理步骤:EBP入栈,保存当前栈帧状态值,已备后面恢复本栈帧时使用。push ebp
  5. 栈帧处理步骤:ESP值赋给EBP,更新栈帧底部。mov ebp,esp
  6. 栈帧处理步骤:给新栈帧分配空间。sub esp,xxx

0x04.函数的返回过程

  1. 保存被调用函数的返回值到 eax 寄存器中。mov eax,xxx
  2. 恢复 esp 同时回收局部变量空间。mov ebp, esp
  3. 将当前栈帧底部保存的前栈帧EBP值弹入EBP寄存器,恢复出上一个栈帧。pop ebp
  4. 弹出当前栈顶元素,从栈中取到返回地址,并跳转到该位置 ret

0x05.图示

(图片转载自https://www.cnblogs.com/clover-toeic/p/3755401.html

发布了62 篇原创文章 · 获赞 70 · 访问量 5479

猜你喜欢

转载自blog.csdn.net/ATFWUS/article/details/104536028
今日推荐