Why does the x86 architecture use two stack registers (esp; ebp)?

My question is simple: why does the x86 architecture use two stack registers ( esp ; ebp )?

The stack frame length was determined at compile time, then I think we can just use one register (e.g. esp ) to access the stack and maintain the base address that used to be in ebp register on the stack (or in other memory areas, but this will lead to a greater decrease in performance)

Is it possible?

+6
source share
2 answers

It all depends on the conditional call, of course, but this usually happens.

The stack pointer can be moved randomly based on the fact that you need to click on or exit the stack at any given time. This can happen at any time inside the function, since you need to temporarily save some data on the stack.

The base pointer is usually set equal to the value for any given stack depth and is used to access the passed parameters (on the one hand) and local variables (on the other hand). It is also used to quickly move the stack pointer after exiting a function.

The reason this is done is to simplify the code so that you do not have to refer to the contents of the stack based on a possibly changing stack pointer. Using a base pointer greatly facilitates the task of generating code (you do not need to know that the stack pointer at any given time, just use a base pointer that remains unchanged throughout the function).

Without this, code that would like to press two copies of a local variable to call the following function would look like this:

  mov eax, [esp+16] ; get var1 push eax ; push it mov eax, [esp+20] ; get var1 again push eax call _somethingElse 

Put aside the fact that in this case you do not restart eax , the point I'm trying to make is that the relative position of the elements from the pointer of the moving stack can uselessly complicate matters.

For example, here is the function encoded in the assembly that follows the general calling convention:

 _doSomething: push ebp ; stack current base pointer mov ebp, esp ; save previous stack pointer sub esp, 48 ; incl 48 bytes local storage ; do whatever you want here, including changing ; esp, as long as it ends where it started. mov esp, ebp ; restore previous stack pointer pop ebp ; and previous base pointer ret ; then return _callIt: mov eax, 7 push eax ; push parameter for function call _doSomething add esp, 4 ; get rid of pushed value : 

If you follow this code, you can see that the ebp inside the function body is a fixed reference point with [ebp] ( ebp content) being the return address, [ebp+4] is the pressed value of 7 and [ebp-N] is the local storage for _doSomething , where N varies from 1 to 48 .

This is the case, regardless of how many elements are pressed or pushed inside the function body.

+10
source

Why does the x86 architecture use two stack registers (esp; ebp)?

According to @gsg's answer to the corresponding question " Do any languages ​​/ compilers use the x86 ENTER instruction with a non-zero nesting level?" x86 architecture was developed 30 years ago as the " Pascal machine ".

See Primer 8086/8088, Stephen P. Morse, Chapter 8: High-Level Programming (Pascal) for rationale from one of the chip developers.

Thus, it includes hardware support for nested and recursive routines (procedures, functions), as in the Pascal programming language , this was an important aspect of the structured programming paradigm to create code that is easier to read / write / maintain.

Hardware support in the form of special CPU instructions allows you to generate code using smaller instructions. Smaller instructions usually also mean faster code.

Is it possible to access the stack frame variable on another Turing complete without using the ebp register?

Yes, but with a different runtime

+2
source

Source: https://habr.com/ru/post/979150/


All Articles