[C语言]函数调用:栈帧的生长 ebp(取参数、局部变量) esp(栈顶) eip(语句执行)

资料来源

第 19 章 汇编与C之间的关系 1. 函数调用
《 Linux C编程一站式学习》

https://akaedu.github.io/book/ch19s01.html

主要心得

  • ebp寄存器要压栈,用ebp来取传入参数局部变量
  • 我对栈帧的理解,从进入当前函数到离开当前函数这个过程中,当前函数造成的全部结果(压栈操作)叫做这个函数的栈帧
  • 但是当前函数需要的传入参数是它的调用者压入的,也就是说传入参数调用者的栈帧里面
  • ebp(当前函数) 是进入当前函数时的栈顶地址(即这个时候的ESP的值
  • 要时刻分清这个是B还是S
  • 我们可以通过ebp(当前函数)+X达到向上去高地址从而拿到传入参数

1、回忆一下这三个寄存器

eip esp ebp

2、函数的调用 main -> foo -> bar

int bar(int c, int d)
{
    int e = c + d;
    return e;
}

int foo(int a, int b)
{
    return bar(a, b);
}

int main(void)
{
    foo(2, 3);
    return 0;
}

2、大致看一眼栈的生长情况,栈随着函数调用的深入 从上往下生长

压栈操作、取传入参数和局部变量.png
  • 传入参数由调用者压栈
  • 传入参数由 ebp(当前函数)+ X取得
  • 局部变量由当前函数压栈
  • 局部变量由ebp(当前函数) - X取得
  • e b p寄存器,基址寄存器,Base Pointer, 注意这个B ,注意这是B,不是S

3、完整的栈生长过程 (函数调用过程) 1->2->3->4

函数调用.png
  • call指令的作用,包括函数返回地址压栈以及跳转
  • esp的减小是压栈引起的,栈从高地址往低地址生长,压栈引起数值变小
  • ebp寄存器的值与函数相关,ebp(main)表示这是main函数的ebp

4、栈帧的串连

栈帧的串连.png
  • 返回地址肯定是要压栈的,不然不知道怎么回来,回来到哪里
  • ebp也要压栈,对的这个B要压栈,要用来 (调用者压入的)传入参数(当前函数压入的)局部变量
  • esp这个S本身是不需要入栈的,一直在变化,它是栈顶

你可能感兴趣的:([C语言]函数调用:栈帧的生长 ebp(取参数、局部变量) esp(栈顶) eip(语句执行))