What are the ESP and the EBP registers?
Asked Answered
N

4

68

I found that the ESP register is the current stack pointer and EBP is the base pointer for the current stack frame. However, I don't understand these definitions (I am just starting to learn how to code in assembler).

What I understand is that ESP points towards the stack itself and EBP points towards whatever is on top of the stack1. But these are just my guesses and they are most likely incorrect. Otherwise, what would a statement like the following mean?

MOV EBP, ESP    

Footnote 1: Editor's note: Yes, that's incorrect. In standard terminology, the "top of the stack" is where ESP points, even though it's the lowest address in the stack frame. By analogy to a stack data structure that grows upward, even though the callstack on x86 (like most ISAs) grows downward.

Noway answered 12/2, 2014 at 4:6 Comment(1)
EBX and EBP are different registers.Gooding
S
99

esp is the stack pointer. ebp is for a stack frame so that when you enter a function, ebp can get a copy of esp at that point. Everything already on the stack, the return address, passed-in parameters, etc. and things that are global for that function (local variables) will now be a static distance away from the stack frame pointer for the duration of the function. esp is now free to wander about as the compiler desires and can be used when nesting to other functions (each needs to preserve the ebp naturally).

It is a lazy way to manage the stack. It makes compiler debugging and understanding compiler-generated code easier, but it uses a register that could have been otherwise general-purpose.

Sontag answered 12/2, 2014 at 4:49 Comment(5)
Thank you. To all who are still trying to understand, for me the key was to tell this to myself : push ebp to the stack for a ebp backup. Then move esp to ebp. Now we can "play" with esp. Before function returns, move back ebp to esp to restore what esp was before we moved esp to ebp. Then pop ebp to restore ebp from the top of the stack.Cheerio
It's all about restoring the stack and register(s) to what it was before the function call.Cheerio
So, is it the MIP's $ra equivalent?Dinnie
@mark_infinite: No, not at all. x86 call pushes a return address onto the stack, MIPS jal puts the return address into a register. On function entry, a MIPS function might need to reserve some stack space and sw $ra, 12($sp) (and restore it at the end before returning) if it wants to make function calls itself. But on x86 the return address is already on the stack upon function entry, pointed-to by the stack pointer. All of this is unrelated to a frame pointer, a pointer to somewhere in the stack that stays fixed even when you alloca or push stack args for further calls.Woodyard
@Dinnie the equivalent to EBP in MIPS is $fp: How does the $fp and $sp register work in MIPS?Embryologist
C
26

Normally EBP is used to backup ESP, so if ESP is changed by the code in a function, all it takes to restore ESP is mov esp, ebp. Since EBP is normally left unchanged by the code in a function, it can be used to access passed parameters or local variables without having to adjust the offsets.

For "stack frame" usage, EBP is pushed onto the stack at the start of any function, so the value of EBP pushed onto the stack is the value of EBP from the function that called the current function. This makes it possible for code or for a debugger to "back trace" through all the instances where EBP was pushed onto the stack, and each instance of an EBP value on the stack could be considered to be the base pointer of a stack frame.

Note that some compilers have an "omit frame pointers" option, in which case EBP is not used to save ESP or as a stack frame pointer, allowing EBP to be used for a variable. The compiler keeps track of ESP, and all local offsets are offsets from the current value of ESP.

Colet answered 12/2, 2014 at 4:16 Comment(0)
A
19

EBP and ESP are remnants of the era, where compilers didn't e.g. have static analysis to detect how many bytes of a stack is needed in a function call. Also the stack was supposed to dynamically grow and shrink during the execution of a function, interrupts would have allowed to trash all the stack from 0 to SP, and spaghetti code was the de facto standard. Actually interrupts (and passing parameters through registers alone) were the designed method to call kernel functions.

In these surroundings one needs to have a fixed point of the stack, where the return address to the caller, local variables and the arguments of a function is always found. Thus the bp register was justified. In this architecture bp was allowed to be indexed ([bp - 300h]), but sp wasn't. Those opcodes/instruction encodings which could have been interpreted as mov ax, [sp + 1111h] were reused for other purposes.

In 386+ and via the introduction of the 'E', ESP gained the property of offset. At this time EBP was freed from the sole purpose, as esp was able to handle both tasks.

Note, that even now EBP points to memory through the stack segment (SS), just like ESP. Other addressing modes (without ESP/EBP as the base) default to the DS segment. (absolute, DI, SI, and/or BX in 16-bit mode, and in 32-bit addressing modes any register can be a base in an addressing mode).

Amelina answered 12/2, 2014 at 4:44 Comment(2)
I find your answer quite informative, but I am not sure what you mean by the very last sentence: "EBX and BX use DS."?Deputize
Historically IA had segment registers; CS for Code, DS/ES for Data and SS for Stack. Each segment accessed only 64kb of memory at a time. 386 had the same architecture, adding FS and GS, but now each segment could have be configured to access anywhere between 1 byte to 4GB of memory. Each instruction or addressing mode has an implicit segment register, through which it accesses the memory. Even later "flat" memory model came the de-facto standard, where each segment register sees everything (but the kernel, which reserves e.g. GS register).Amelina
M
8

The ESP register is the stack pointer for the system stack. It is rarely changed directly by a program but is changed when data is pushed onto the stack or popped from the stack. One use for the stack is in procedure calls. the address of the instructions following the procedure call instruction is stored on the stack. the EBP register pointers to the base. normally the only data item accessed in the stack is the one that is at the top of the stack. Although the EBP register is often used to mark a fixed point in the stack other than the top of the stack, for example of such data are the parameters. They are offset from the stack EBP top of the base pointer after the return address. So you will see something like EBP+0x8, EBP+0xC, this is parameters as in 1 and 2 respectively.

enter image description here

Understanding the stack is very crucial in programming in assembly language as this can affect the calling conventions you will be using regardless of the type. For example, even the cdecl or __stdcall is also dependent on the ESP and EBP registers, and others too in some way depend on some registers and the stack.

Mccomb answered 20/3, 2020 at 11:33 Comment(1)
Note that all of this only applies to code that happens to use EBP as a frame pointer. That is optional in modern systems. Debug builds still do it. The calling conventions themselves like stdcall don't specify anything about how the caller or callee must use EBP. It's totally fine to load a stack arg with something like mov eax, [esp + 4] / ret 4 to implement a stdcall function that returns an integer arg.Woodyard

© 2022 - 2024 — McMap. All rights reserved.