Заставить GCC поместить аргументы в стек перед вызовом функции (используя инструкцию PUSH)
Я начал разработку небольшой 16-битной ОС под GCC / G ++. Я использую кросс-компилятор GCC, который я скомпилировал под Cygwin, я помещаю asm (".code16gcc») в качестве первой строки каждого файла .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.s, потому что КОДА СБОРКИ GCC генерирует выглядит следующим образом (яМы также включили источник для ясности):
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, учитывая, что это ограничивает использование встроенной сборки для сложных вещей. :( Пожалуйста, оставьте ответ, если у вас есть предложение.