Wymuś GCC, aby wypchał argumenty na stosie przed wywołaniem funkcji (za pomocą instrukcji PUSH)

Zacząłem tworzyć mały 16-bitowy system operacyjny w GCC / G ++. Używam kompilatora krzyżowego GCC, który skompilowałem pod Cygwinem, umieszczam asm (". Code16gcc n") jako pierwszą linię każdego pliku .CPP, używając składni Intel ASM i linii poleceń do kompilacji i łączenia Plik .CPP wygląda tak:

G++: i586-elf-g++ -c $(CPP_FILE) -o $(OBJECT_OUTPUT) -nostdinc -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fpermissive -masm=intel

LD: i586-elf-ld -T $(LD_SCRIPT) $(OBJECT_OUTPUT) -o $(BINARY_OUTPUT)

Problemem, przed którym obecnie stoję, jest sposób, w jaki GCC tłumaczy kod wywołujący funkcje na zespół.

Aby być bardziej szczegółowym, zamiast używać instrukcji PUSH do przekazywania argumentów, GCC "oblicza" przesunięcia względem ESP, których argumenty powinny być zlokalizowane, a następnie używa instrukcji MOV do ręcznego zapisu stosu.

Nie jest to dla mnie korzystne, ponieważ polegam na instrukcji PUSH w moim kodzie zespołu. Aby zilustrować mój problem jaśniej, weź te dwie funkcje:

void f2(int x);

void f1(){
    int arg = 8;
    asm("mov eax, 5");
    asm("push eax");
    f2(arg);
    asm("pop eax");
}
void f2(int x){
}

W funkcji f1 zapisuję EAX za pomocą instrukcji PUSH i oczekiwałbym przywrócenia go do 5 po wywołaniu f2 i wykonaniu instrukcji „POP EAX”. Okazuje się jednak, że EAX staje się 8, a nie 5. To dlatego, że GODZIENNY KOD GCC generuje wygląda w ten sposób (ja również dodałem źródło dla jasności):

void f1()
C++: {
    push ebp
    mov ebp,esp
    sub esp,byte +0x14

    C++: int arg = 8;
        mov dword [ebp-0x4],0x8

    C++: asm("mov eax, 5");
        mov eax,0x5

    C++: asm("push eax");
        push eax

    C++: f2(arg);
        mov eax,[ebp-0x4]
        mov [dword esp],eax =======>>>>>> HERE'S THE PROBLEM, WHY NOT 'PUSH EAX' ?!!
        call f2

    C++: asm("pop eax");
        pop eax

C++: }
    o32 leave
    o32 ret

void f2(int x)
C++: {
    push ebp
    mov ebp,esp
C++: }
    pop ebp
    o32 ret

Próbowałem użyć niektórych flag kompilacji G ++, takich jak -mpush-args lub -mno-push-args i innej, której nie pamiętam, a GCC nadal nie chce używać PUSH. Używana przeze mnie wersjai586-elf-g++ (GCC) 4.7.2 (Kompilator krzyżowy ponownie skompilowany w Cygwin).

Z góry dziękuję!

AKTUALIZACJA: Oto strona, którą znalazłem:http://fixunix.com/linux/6799-gcc-function-call-pass-arguments-via-push.html

Wydaje się to naprawdę głupie dla GCC, biorąc pod uwagę, że ogranicza to użyteczność montażu inline dla złożonych rzeczy. :( Proszę zostawić odpowiedź, jeśli masz sugestię.

questionAnswers(2)

yourAnswerToTheQuestion