Заставить GCC поместить аргументы в стек перед вызовом функции (используя инструкцию PUSH)

Я начал разработку небольшой 16-битной ОС под GCC / G ++. Я использую кросс-компилятор GCC, который я скомпилировал под Cygwin, я помещаю asm (". Code16gcc \ n") в качестве первой строки каждого файла .CPP, используя синтаксис Intel ASM и командные строки для компиляции и компоновки Файл .CPP выглядит так:

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)

Проблема, с которой я сейчас сталкиваюсь, заключается в том, как GCC переводит код вызова функции в сборку.

Чтобы быть более конкретным, вместо использования инструкции PUSH для передачи аргументов, GCC «вычисляет» смещения относительно ESP, в которых должны располагаться аргументы, а затем использует инструкцию MOV для записи стека вручную.

Это не выгодно для меня, так как я полагаюсь на инструкцию PUSH в своем коде сборки. Чтобы проиллюстрировать мою проблему, возьмите эти 2 функции:

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){
}

В функции f1 я сохраняю EAX с помощью инструкции PUSH, и я ожидаю, что он будет восстановлен до 5 после вызова f2 и выполнения инструкции «POP EAX». Тем не менее, получается, что EAX становится 8, а не 5. Это потому, что GCC ASSEMBLY CODE генерирует выглядит следующим образом (я также включил источник для ясности):

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

Я попытался использовать некоторые флаги компиляции G ++, такие как -mpush-args или -mno-push-args, и еще один, который я не могу вспомнить, и GCC по-прежнему не хочет использовать PUSH. Я использую версиюi586-elf-g++ (GCC) 4.7.2 (Кросс-компилятор перекомпилирован в Cygwin).

Заранее спасибо!

ОБНОВИТЬВот веб-страница, которую я нашел:http://fixunix.com/linux/6799-gcc-function-call-pass-arguments-via-push.html

Это просто кажется глупостью для GCC, учитывая, что это ограничивает использование встроенной сборки для сложных вещей. :( Пожалуйста, оставьте ответ, если у вас есть предложение.

Ответы на вопрос(2)

Ваш ответ на вопрос