Search code examples
assemblycompilationstackcompiler-optimizationred-zone

why preserve stack space for local variables?


I'm new to assembly language and I was wondering about local variables, why do we (or the compilers) preserve a space for them on the stack usually by decrement the "ESP" register at the prologue of the procedure and as the procedure ends we assign the "ESP" it's old value again. like this code sample :

; a procedure that create the stack frame then assign 10, 20 values for two local variables then return to caller

two_localv_proc PROC
push ebp
mov ebp,esp
sub esp,8
mov DWORD PTR [ebp-4],10
mov DWORD PTR [ebp-8],20
mov esp,ebp
pop ebp
ret
two_localv_proc ENDP

the last code snippet will do exactly if we removed the (sub esp,8) line and the (mov esp,ebp) line, to be as this

 two_localv_proc PROC
push ebp
mov ebp,esp
mov DWORD PTR [ebp-4],10
mov DWORD PTR [ebp-8],20
pop ebp
ret
two_localv_proc ENDP

so why we (or the compilers) do such behavior! , why don't we just use the stack memory to store our local variables as long as the "ESP" pointer will not affected by storing values on the stack with codes like:

mov DWORD PTR [ebp-8],20

Solution

  • In general, you can only use the stack above the stack pointer. The stack pointer defines the end of the stack. Accessing under the stack pointer may or may not work. It especially won't work if you call another function, since the return address would be pushed and also the called function would start using the stack from the stack pointer, thereby overwriting your locals. Even in leaf functions, asynchronous things such as signal handlers may use the stack, and they also assume everything under the stack pointer is unused.

    Furthermore, the OS may be growing your stack on-demand, and it also uses the stack pointer for that. If you access under the stack pointer, the memory might not even be mapped, and if the OS catches you doing that your program will crash.

    Note that some calling conventions, such as the x86-64 abi, allow for a so-called red zone under the stack pointer. This area is guaranteed to be unmodified and can be used in leaf functions for the locals without adjusting the stack pointer.