栈帧的概念及其应用-函数调用的原理

1,695 阅读2分钟

什么是栈帧(Stack Frame)?

栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。

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

  • 函数的返回地址和参数
  • 临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量
  • 函数调用的上下文

栈是从高地址向低地址延伸,一个函数的栈帧用EBP和ESP这两个寄存器来划定范围。EBP指向当前栈帧的底部,ESP始终指向栈帧的顶部。

  • EBP寄存器又被称为帧指针(Frame Pointer)
  • ESP寄存器又被称为栈指针(Stack Pointer)

函数调用的过程

  1. 参数入栈。参数按照调用约定依次压入系统栈中,在C语言中是按照自右向左的顺序
  2. 保存现在位置。将当前代码区调用指令的下一条指令地址压入栈中,供函数返回时继续执行
  3. 跳转到子函数

其中栈帧调整的过程:

  1. EBP帧指针入栈:保存当前栈帧状态值,方便函数返回之后的现场恢复
  2. 将ESP栈指针值装入EBP帧指针,更新栈帧底部:目的是将当前栈帧切换到新栈帧 这时EBP帧指针指向栈顶,而此时栈顶就是图中的OLD EBP
  3. 给新栈帧分配空间:把ESP减去所需空间的大小(因为栈是从高地址向低地址),抬高栈顶

函数返回时栈帧的操作

  1. 保存被调用函数的返回值到寄存器中
  2. 给ESP加上栈帧的大小,降低栈顶,回收当前栈帧的空间(即弹出当前帧)
  3. 将当前栈帧底部保存的前栈帧EBP值弹入EBP寄存器,恢复出旧栈帧。
  4. 弹出当前栈顶元素,从栈中取到返回地址,并跳转到该位置

参考

  1. zhuanlan.zhihu.com/p/77663680
  2. juejin.cn/post/684490…