Does the pointer point to the stack pointer framework?

As far as I understand, the stack pointer points to the "free" memory on the stack, and the "push" of data on the stack is written to the location indicated by the stack pointer, and increases / decreases it.

But is it possible to use offsets from the frame pointer to achieve the same, thereby preserving the register. The overhead associated with adding offsets to the frame pointer is pretty much the same as the overhead of incrementing and decreasing the stack pointer. The only advantage that I see is that access to data from the "top" (or bottom) will be faster if it is not a push or pop operation, for example. just reading or writing to this address without increasing / decreasing. But then again, such operations will require one additional loop using the frame pointer, and one additional register will be used for general use.

It seems that only the frame pointer really is needed. And this even requires a much larger goal than just modifying the data in the current stack frame, for example, for use in debugging and for expanding the stack. Did I miss something?

+1
assembly stack pointers frame
09 Oct '14 at 12:13
source share
2 answers

Well, yes, and actually common to 64-bit code generators. However, there are complications that do not make it universal. The strict requirement is that the value of the stack pointer is known at compile time, so the code generator can reliably generate an offset. This does not work if:

  • The language runtime provides non-trivial alignment guarantees. In particular, the problem is in 32-bit code when the stack frame contains 8-byte variables, such as double. Access to an incorrectly aligned variable is very expensive (x2 if it is offset by 4, x3 if it crosses the L1 cache line) and may invalidate the memory model guarantee. The code generator usually cannot assume that the function is being entered with the stack aligned, therefore it is necessary to generate the code in the function prolog, this may lead to a decrease in the stack pointer by an additional 4 bytes.

  • The language runtime provides the ability to dynamically allocate stack space. Very often and desirable, it is a very cheap and fast memory. Examples are alloca () in CRT, variable length arrays in C99 +, the stackalloc keyword in C #.

  • The language runtime should provide a reliable way to move the stack. Common in exception handling, the implementation of the sandbox, which should be able to detect the rights of the caller, collect garbage languages โ€‹โ€‹that should be able to detect pointers to objects. Of course, there are many possible ways to do this, but using the base pointer and saving the call base pointer to a known location on the stack stack makes it simple.

+4
Oct 09 '14 at 13:15
source share

Your question should be: is the frame pointer redundant?

In most cases, code can only be written using the stack pointer and not use the pointer on most processors (some processors, such as x86 in 16-bit mode, have restrictions on access to the stack pointer, so a frame pointer is required).

One example:

mov ebp, esp push esi mov eax, [ebp+4] push edi mov eax, [ebp+8] 

can also be written as:

 push esi mov eax, [esp+8] push edi mov eax, [esp+16] 

Some special cases, such as the alloca () function, however require the use of both frame and stack pointers.

The stack pointer is never redundant:

You must consider that the stack pointer is used by interrupts. Interrupts are functions of the operating system that are automatically called by the hardware (instead of the CALL instruction) when certain conditions are met (for example, an electrical signal is received from a USB port).

Since such interrupts suggest that memory below the stack pointer is free, it would be a very bad idea to use memory under the stack pointer; if an interrupt occurs, than the memory below the stack pointer will be destroyed!

In MIPS processors (for example), this is a pure convention, which of the registers is a stack pointer; you can also say that R9 is the stack pointer, and the stack is not at address R9, but at address R9 + 1234. The 64-bit Sparc calling convention uses such a strange convention for the stack pointer. However, this requires that all code (including the operating system and all interrupts) use the same convention.

On x86 processors, this is impossible, because the processor itself will consider that the memory below the stack pointer is free: PUSH and CALL instructions will be written to memory under the stack pointer, and in case of interruption, the processor will store information at the address pointed to by the stack pointer, without the ability to change this behavior!

+2
Oct 09 '14 at 12:31 on
source share



All Articles