为什么基指针值存储在堆栈中

时间:2016-03-03 03:10:42

标签: c++ c compilation

从这个网站: 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);
}
内存中的

如下图所示:

enter image description here

我不明白为什么基指针从堆栈中获取内存,它不能只是存储在像堆栈指针这样的寄存器中,只是指向他需要的位置? (我知道当stackpointer进行推送和弹出时,基本指针用于更容易地查找变量,但我不明白为什么它的值存储在堆栈中,而不仅仅是寄存器!),非常感谢你的帮助(我担心我错过了一些非常重要的事情)

编辑: 这可能会让我更加困惑:在图片中他们展示了EBP' (注册表),'保存了ebp'。我不明白为什么有两个......

2 个答案:

答案 0 :(得分:2)

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

仍有一些理由在进入程序/功能时保存EBP:除非堆栈损坏,否则它很容易走路。 EBP指向EBP的先前值,该值指向前一个值,依此类推,直到堆栈为止。如果您正在调试(例如),这使得堆栈跟踪变得非常容易。如果你必须浏览一些你没有符号的代码,你可以走过它们,找到你理解的早期堆栈帧,并详细检查它们。

相比之下,如果直接使用ESP,它会在输入函数时调整,以便为该函数的局部变量腾出空间。您需要知道调整了多少以回到之前的堆栈帧。如果你到达了一个没有信息的地方,并且你不知道ESP在进入该功能时调整了多少,你就会陷入困境(没有拆解代码来找到堆栈调整,以便你可以取消它。)

答案 1 :(得分:1)

这样可以递增堆栈指针以适应新的堆栈帧。当返回时,基指针会弹出到堆栈指针中以恢复旧值。

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

相关问题