强制GCC(使用PUSH​​指令)调用函数之前推栈参数 [英] Force GCC to push arguments on the stack before calling function (using PUSH instruction)

查看:389
本文介绍了强制GCC(使用PUSH​​指令)调用函数之前推栈参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开始制订下GCC / G ++小的16位操作系统。
我使用的是GCC交叉编译器,这是我在Cygwin下编译,我把ASM(。code16gcc \\ n)作为每个.cpp文件中的第一行,采用英特尔ASM语法和编译命令行并链接一个.cpp文件是这样的:

I have started developing a small 16-bit OS under GCC/G++. I am using a GCC cross-compiler, which I compiled under Cygwin, I am putting asm(".code16gcc\n") as the first line of each .CPP file, using Intel ASM syntax and the command lines for compiling and linking a .CPP file look like this:

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的方式转换函数调用code到装配。

The problem I am currently facing is the way GCC translates function-calling code into assembly.

要更具体,而不是使用PUSH​​指令传递参数,海湾合作委员会计算的偏移量相对于ESP中的参数应位于,然后使用MOV指令手动编写栈。

To be more specific, instead of using the PUSH instruction to pass the arguments, GCC "calculates" the offsets relative to ESP the arguments should be located at, and then uses the MOV instruction to write the stack manually.

这是不是对我有利,因为我靠我的组装code中的PUSH指令。为了说明我的问题更清楚,把这些功能2:

This is not beneficial for me, since I rely on the PUSH instruction in my assembly code. To illustrate my problem clearer, take these 2 functions:

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这是因为大会code GCC产生这样的外观(我已经包含在源以及为清楚起见):

In function f1, I am saving EAX using the PUSH instruction, and I would expect to have it restored to 5 after calling f2 and executing the "POP EAX" instruction. It turns out however that EAX becomes 8, not 5. That's because the ASSEMBLY CODE GCC generates looks like this (I've included the source as well for clarity):

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-推指定参数和另外一个我不记得和GCC仍然不希望使用PUSH​​尝试。我使用的版本是 i586的小精灵-G ++(GCC)4.7.2 (交叉编译Cygwin中重新编译)。

I have tried using some G++ compilation flags like -mpush-args or -mno-push-args and another one which I can't remember and GCC still doesn't want to use PUSH. The version I'm using is i586-elf-g++ (GCC) 4.7.2 (Cross-Compiler recompiled in Cygwin).

感谢你在前进!

更新:这里有一个网页,我发现:的 http://fixunix.com/linux/6799-gcc-function-call-pass-arguments-via-push.html

UPDATE: Here's a webpage I've found: http://fixunix.com/linux/6799-gcc-function-call-pass-arguments-via-push.html

这只是似乎很愚蠢的GCC做的,考虑到它限制了内联汇编的复杂的东西可用性。 :(如果你有一个建议,请给一个答案。

That just seems really stupid for GCC to do, considering that it limits the usability of inline assembly for complex stuff. :( Please leave an answer if you have a suggestion.

推荐答案

我一直很幸运,找到一个解决这个问题,但它最后做什么,我想要它做的。
这里是什么版本的GCC 4.7.2手动状态:

I've been very lucky finding a solution to this problem, but it finally does what I want it to do. Here's what the GCC manual for version 4.7.2 state:

-mpush-args
-mno-push-args
Use PUSH operations to store outgoing parameters. This method is shorter
and usually equally fast as method using SUB/MOV operations and is enabled
by default. In some cases disabling it may improve performance because of
improved scheduling and reduced dependencies.

-maccumulate-outgoing-args
If enabled, the maximum amount of space required for outgoing arguments will
be computed in the function prologue. This is faster on most modern CPUs
because of reduced dependencies, improved scheduling and reduced stack usage
when preferred stack boundary is not equal to 2. The drawback is a notable
increase in code size. This switch implies ‘-mno-push-args’.

我说我很幸运,因为-mpush-ARGS不工作,什么工作是不是-mno累加-传出-ARGS,它甚至没有记录!

I'm saying I am lucky because -mpush-args does not work, what works is instead "-mno-accumulate-outgoing-args", which is not even documented!

这篇关于强制GCC(使用PUSH​​指令)调用函数之前推栈参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆