igorpoolday
igorpoolday

Reputation: 1

Is the red zone a problem for inline assembly for 32-bit x86 with MSVC?

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;
}

Upvotes: 0

Views: 322

Answers (1)

Peter Cordes
Peter Cordes

Reputation: 364287

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.

Upvotes: 2

Related Questions