ESP和EBP寄存器是什么?

问题描述 投票:27回答:3

我发现ESP寄存器是当前堆栈指针,而EBP是当前堆栈帧的基址指针。但是,我不理解这些定义(我只是开始学习如何在汇编器中编码)。

我了解的是,ESP指向堆栈本身,而EBP指向堆栈顶部的任何内容1。但这只是我的猜测,很可能是错误的。否则,如下所示的语句意味着什么?

MOV EBP, ESP    

脚注1:编者注:是的,那是不正确的。用标准术语来说,“栈顶”是ESP指向的位置,即使它是栈帧中的最低地址也是如此。类似于向上增长的堆栈数据结构,即使x86上的调用堆栈(像大多数ISA一样)向下增长。

assembly
3个回答
30
投票

esp是堆栈指针,ebp是/是一个堆栈帧,因此当您输入函数时,ebp可以在该点获得esp的副本,在此之前堆栈上的所有内容都会发生,返回地址,传入参数,等等。现在,对于该函数而言全局的东西(局部变量)将在函数持续时间内与堆栈帧指针保持静态距离。 esp现在可以按照编译器的要求随意游荡,并且可以在嵌套到其他函数时使用(每个函数都需要自然保留ebp)。

这是管理堆栈的一种惰性方法。使编译器的调试容易得多,使编译器生成的代码更容易理解,但是会烧写可能是通用的寄存器。


13
投票

通常,ESP用于备份ESP,因此,如果功能中的代码更改了ESP,则恢复ESP所需的全部是mov ESP,EBP。同样,由于EBP通常由函数中的代码保持不变,因此可以使用EBP来访问传递的参数或局部变量,而无需调整偏移量。

对于“堆栈框架”用法,EBP在任何函数的开始处都被压入堆栈,因此,被压入堆栈的EBP的值就是来自调用当前函数的函数的EBP的值。这使得代码或调试器可以在将EBP推入堆栈的所有实例中进行“回溯”,并且堆栈上EBP值的每个实例都可以视为堆栈帧的基本指针。 。

请注意,某些编译器具有“省略帧指针”选项,在这种情况下,EBP不用于保存ESP或用作堆栈帧指针。相反,编译器会跟踪ESP,并且所有本地偏移量都是相对于ESP当前值的偏移量。


7
投票

EBP和ESP是那个时代的残存者,当时编译器没有进行静态分析,以检测函数调用中需要堆栈的多少个字节。同样,堆栈应该在函数执行过程中动态增长和收缩,中断将使从0到SP的所有堆栈都报废,而意粉代码实际上是标准。实际上,中断(仅通过寄存器传递参数)是调用内核函数的设计方法。

在这些环境中,需要具有堆栈的固定点,在此始终找到调用方的返回地址,局部变量和函数的自变量。因此,bp寄存器是合理的。在此体系结构中,允许对bp进行索引([bp-300h]),但不允许对sp进行索引。那些本可以解释为mov ax, [sp + 1111h]的操作码/指令编码已重新用于其他目的。

在386+和通过引入'E',ESP获得了offset属性。此时EBP脱离了唯一的目的,因为esp能够处理这两个任务。

注意,即使现​​在EBP也通过堆栈segment(SS)指向内存,就像ESP一样。其他寻址模式(不以ESP / EBP为基础)默认为DS段。 (在16位模式下为绝对,DI,SI和/或BX,在32位寻址模式下,任何寄存器都可以在寻址模式下为基。)

© www.soinside.com 2019 - 2024. All rights reserved.