rsp doesn’t move when entering new function [duplicate]

The x86-64 System V ABI has a 128-byte red zone below RSP that is safe from asynchronous clobbering, i.e. is “owned” by the function.

It looks like you compiled int foo{ int x = 4; return 0; } with gcc -O0 (optimizations disabled), and gcc chose to keep x in the instead of adjusting rsp to “reserve”https://stackoverflow.com/”allocate” the stack space. (See the red-zone tag wiki for more links / info.)

This is the whole point of the red-zone: to save those sub/add instructions in leaf functions.

BTW, looking at un-optimized code is usually a waste of time. -O1 at least is more readable, and -O2 / -O3 are relevant for code that you should actually care about. See also How to remove “noise” from GCC/clang assembly output?.

In programs with no signal handlers, the entire stack region can effectively be used as a red-zone. example: code-golf extended-precision Fibonacci using esp as an array pointer because pop is fast and compact. (AFAIK, signal handlers are the only thing that will asynchronously clobber memory below rsp). The red-zone lets compilers take advantage of it without needing a special compile option (and there is no such option for 32-bit mode where the SysV ABI doesn’t define a red-zone). Proving that there are no signal handlers is probably not feasible even with whole-program optimization.

I only see how the address of variables is directly access through ebp

No, you don’t. Access through ebp would fault in 64-bit code, because the stack is outside the low 4GB of address space (by default on Linux at least). Pointers are 64-bit, so gcc uses rbp to access them.

Using an address-size prefix to encode movl $0x4,-0x4(%ebp) in 64-bit mode would be a waste of code size even if it didn’t fault.

Fun fact: in the x32 ABI (ILP32 in long mode) where pointers are 32-bit, gcc often uses the address-size prefix instead of extra instructions to truncate possible high garbage in registers and make sure addressing modes wrap at 2^32 instead of going outside 4GB (with a signed displacement for example). Instead of doing this optimally, it defaults to just stupidly using address-size prefixes on every instruction with an explicit memory operand. But a recent patch gets it to always use 64-bit rsp instead of using address-size prefixes even for esp.

Leave a Comment