【问题标题】:why base pointer value is stored in the stack为什么基指针值存储在堆栈中
【发布时间】:2016-03-03 13:42:18
【问题描述】:

来自这个网站: http://eli.thegreenplace.net/2011/02/04/where-the-top-of-the-stack-is-on-x86/ 我看到这个程序栈:

int foobar(int a, int b, int c)
{
    int xx = a + 2;
    int yy = b + 3;
    int zz = c + 4;
    int sum = xx + yy + zz;

    return xx * yy * zz + sum;
}

int main()
{
    return foobar(77, 88, 99);
}

内存如下图所示:

我不明白为什么基指针从堆栈中获取内存,它不能像堆栈指针一样存储在寄存器中,只是指向他需要的地方吗? (我知道当stackpointer进行push和pop时,基指针用于更容易找到变量,但我不明白为什么它的值存储在堆栈中,而不仅仅是寄存器中!),非常感谢您的帮助(恐怕我错过了一些非常重要的东西)

编辑: 可能这更有助于我的困惑:在图像中,它们显示“EBP”(寄存器)和“保存的 ebp”。我不明白为什么有两个...

【问题讨论】:

  • 为什么返回地址必须存储在堆栈中,而不仅仅是寄存器中?
  • 我了解到basepointer已经有一个寄存器EBP了,但是返回地址没有。在图像中,它们显示“EBP”(寄存器)和“保存的 ebp”。我不明白为什么有两个...
  • 基/帧指针像链表一样工作; EBP指向当前基指针,当前基指针指向前一个基指针,以此类推。
  • 返回地址在调用前后肯定有一个寄存器,即程序计数器(PC)或指令指针(IP)——名称因架构而异。除非您正在执行一些面向继续的调用,否则返回地址只不过是“保存的程序计数器”,它有助于在被调用函数返回时在调用者中恢复执行。
  • @Melak47 这很有意义......如果你有时间把它放在答案中,我想我应该投票给你

标签: c++ c compilation


【解决方案1】:

首先,您应该意识到这种堆栈框架样式不再是真正需要的。大多数当前的编译器可以(并且确实)消除将 [E]BP 保存在堆栈上,并在进入函数时将 [E]SP 复制到 [E]BP。有一次(16 位代码)这是需要的,因为 BP 可以充当基址寄存器,但 SP 不能。这意味着你不能做像-7[SP] 这样的事情,但你可以做-7[BP]。然而,在 386 位和 32 位代码中,情况不再如此——您可以使用 ESP(或任何其他寄存器)作为基址寄存器。

尽管如此,仍有一些理由在进入过程/函数时保存 EBP:除非堆栈损坏,否则它真的很容易遍历。 EBP 指向 EBP 的前一个值,EBP 指向前一个值,以此类推,一直沿堆栈向下。如果您正在调试(例如),这可以很容易地进行堆栈跟踪。如果您必须遍历一些没有符号的代码,您可以遍历它们,找到您理解的较早的堆栈帧,并详细检查它们。

相比之下,如果您直接使用 ESP,它会在进入函数时进行调整,以便为该函数的局部变量腾出空间。您需要知道它被调整了多少才能回到上一个堆栈帧。如果你到达一个你没有任何信息的点,并且你不知道在进入该函数时调整了多少 ESP,那么你几乎被卡住了(没有反汇编代码来找到堆栈调整,所以你可以取消它)。

【讨论】:

    【解决方案2】:

    这样堆栈指针可以递增以容纳新的堆栈帧。当需要返回时,基指针被弹出到堆栈指针中以恢复旧值。

    您不能假设有任何寄存器,更不用说备用寄存器了,并且将寄存器专用于在函数退出之前肯定不会使用的东西会浪费宝贵的资源。

    【讨论】:

      猜你喜欢
      • 2013-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-17
      • 1970-01-01
      • 1970-01-01
      • 2019-11-23
      相关资源
      最近更新 更多