0

Red zone stack diagram Does the red zone exist in x86 ? And even if not, can you explain to me by AMD64 ?

Where is the red zone ? WIKI: "the red zone is a fixed-size area in a function's stack frame below the current stack pointer" "current stack pointer": the meaning this area (128 bytes if i understand) always below of the updated stack pointer no distance ? or we have from the start some distance between, and this distance get closer and closer when i sub the esp ?

Should I give importance to the red zone ? always when i sub the esp ? like in push or call function or create locals (caller callee) ?

If I create local variables I will get to the red zone ? and is it dangerous ? (leaf/not leaf functions)

Does it matter if I call a leaf/not leaf function ?

To avoid this area should I do: sub esp, 128 ? and if yes wen ? before each sub the esp ?

#include <stdio.h>

int main() {
    int x = 5, y, z;
    // push
    __asm {
        sub esp, 4 // allocate cell on the stack (allocate static memory) 
        // we cant put 2 addresses on the address bus  (we cant do: mov memory, memory)
        mov eax, dword ptr [x] // save value of x on eax 
        mov [esp], eax         // insert to the allocated cell value of eax (5 from x) 
    }
    // peek
    __asm {
        mov eax, [esp] // the value of what is at the top of the stack
        mov dword ptr [y], eax // copy to y
    }
    printf("y = %d\n", y);
    // pop 
    __asm {
        mov eax, [esp] // the value of what is at the top of the stack
        mov dword ptr[z], eax // copy to z
        add esp, 4 // deallocate cell on the stack (deallocate static memory) 
    }
    printf("z = %d", z);
    return 0;
}

or like this:

#include <stdio.h>

void f(int x) {
    printf("%d\n", x);
}

void g() {
    int x = 5;
    f(x);
}

int main() {
    __asm { 
        mov eax, 3
        push eax
        call f 
        add esp, 4
    }
    __asm { call g }
    return 0;
}
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    I'm not aware of any non-64-bit x86 ABIs that have a red zone. The System V AMD64 ABI for x86-64 does have a red zone. – Thomas Jager Jul 20 '22 at 17:48
  • Looks like quite a few architectures have red zones depending on OS and ABI. But it's not fixed and is ABI specific. Also the red zone is irrelevant unless you're coding a leaf function or in kernel mode where you have to compensate for it. That's why the red zone has a fixed size, so kernel mode can clobber that portion of the stack if needs must – Mgetz Jul 20 '22 at 17:52
  • @igorpoolday as far as I'm aware x86 does not use a red zone in 32bit or 16bit code. It's only use in x86-64 mode AKA long mode. – Mgetz Jul 20 '22 at 17:56
  • 3
    The presence and size of a red zone depends on the ABI you are using. What ABI are you using? – Raymond Chen Jul 20 '22 at 17:58
  • 1
    Related: [Inline assembly that clobbers the red zone](https://stackoverflow.com/q/6380992) / [How do I tell gcc that my inline assembly clobbers part of the stack?](https://stackoverflow.com/q/39160450) if you're actually using inline-assembly – Peter Cordes Jul 20 '22 at 18:06
  • @igorpoolday The red zone is always the 128 byte below the stack pointer. Everything else naturally follows from that. If you move the stack pointer, the red zone moves with it. If you call a function, it'll most likely trash whatever was in the red zone. The only thing that is guaranteed is that the kernel won't trash it, unlikely everything that is below the red zone. – fuz Jul 20 '22 at 19:08
  • @igorpoolday No, as others have already said multiple times: the red zone is a thing in the amd64 SysV calling convention only. There is no 32 bit calling convention using it. And even on amd64, you can simply ignore the red zone. You have the option to make use of this space, you don't have to. – fuz Jul 20 '22 at 19:17
  • 3
    Do not deface your questions! If your question has been answered, mark an answer as accepted. If no answer matches the solution you found, you are encouraged to post the solution you found as an answer and mark that as accepted. But do not edit your question like you just did. – fuz Jul 20 '22 at 19:55
  • @ErikEidt: It was pretty obvious to me that the original form of the question wasn't answerable, since it was talking about a red-zone but then saying stuff about ESP (not RSP). And there were already comments that no 32-bit x86 calling convention included a red zone. I thought it was vastly more likely that the OP was confused, rather than asking about a hypothetical case or red-zones in general. The current form of this question is pretty much what I expected it probably was, which is why I waited to answer until seeing details. – Peter Cordes Jul 20 '22 at 20:01

1 Answers1

2

No 32-bit x86 calling conventions use a red-zone, and MSVC can't target the x86-64 convention that does (AMD64 System V, used on all non-Windows systems).

Since you use push eax (and stack args at all), your code can only compile for 32-bit mode, so you don't need to worry about a red-zone. That's true even if you were compiling with clang -fasm-blocks e.g. for Linux to allow asm{} syntax, instead of with MSVC or clang-cl for Windows.


If you were writing different code with x86-64 64-bit registers, for a non-Windows OS with clang -fasm-blocks or with normal GNU C inline asm (like asm("instructions" : "+r"(x) : "r"(y) : "rax")), then you would need to worry about calling functions (or using the stack at all) from inside inline asm.

For that, see Calling printf in extended inline ASM for how to skip past the red-zone before using the stack, and how to declare clobbers on all the call-preserved registers.

Unfortunately there's no way to tell GCC/clang that you want to clobber the red-zone, so unless you build that with with -mno-red-zone, you need to work around it.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Cords look at my code with calle with inline, it will work too ? – igorpoolday Jul 20 '22 at 19:02
  • 1
    @igorpoolday No, your inline assembly is incorrect. Do not modify the stack pointer in inline assembly under any circumstances. Instead, define a local variable and save the value in question there. – fuz Jul 20 '22 at 19:18
  • 1
    @igorpoolday No, no push/pop at all. No changing the value of `esp`! If you have a specific error you are trying to fix, please edit your question and add the code for that (or ask a new question). The solution is most likely not that you'll have to “clean the stack” (whatever that means). – fuz Jul 20 '22 at 19:54
  • @fuz: I *think* MSVC lets you use push/pop, as long as you restore ESP to its original value before leaving the asm block. (There's no red-zone, and it always uses `[ebp + offset]` to access local variables like `[sum]` in functions that contain an `asm{}` block.) It's not particularly efficient, but MSVC inline asm is inefficient in general. Do you have any source or evidence for it being unsafe in MSVC (or `clang -fasm-blocks`) inline asm to do this? – Peter Cordes Jul 20 '22 at 19:57
  • @PeterCordes I do not have a source and I might be wrong indeed. – fuz Jul 20 '22 at 19:58
  • 1
    @MichaelPetch: The OP is throwing a temper tantrum(?) and closed it after having their vandalizing edits rolled back several times. I already flagged it for moderator attention, noting the inappropriate dup closure as well as the bad edits. I assume Erik voted to close for some other reason, and then the OP picked my highest-voted answer as a duplicate. Users can single-handedly close their own questions, but if they don't have a gold badge, it shows up as Community casting the votes. – Peter Cordes Jul 20 '22 at 20:07