免责声明:我不知道MIPS,但我确实知道一些X86,而且我认为原则应该是一样的..
在平时的函数调用约定,编译器会推n
值到堆栈上传递给函数foo
。但是,您可以使用fastcall
约定来告诉gcc通过寄存器来传递值。 (MSVC也有这个选项,但我不确定它的语法是什么。)
test.cpp:
int foo1 (int n) { return ++n; }
int foo2 (int n) __attribute__((fastcall));
int foo2 (int n) {
return ++n;
}
编译以上g++ -O3 -fomit-frame-pointer -c test.cpp
,我得到foo1
:
mov eax,DWORD PTR [esp+0x4]
add eax,0x1
ret
正如你可以看到,它读取从堆栈中值。
而这里的foo2
:
lea eax,[ecx+0x1]
ret
现在从寄存器直接取值。
当然,如果你内联函数,编译器会做一个简单的加法在较大的函数体中,无论您指定的调用约定。但是,当你无法将其内联时,这将会发生。
2免责声明:我不是说你应该不断地在事后的编译器。在大多数情况下,这可能不切实际和必要。但不要认为它会产生完美的代码。
编辑1:如果你在谈论普通的局部变量(而不是函数参数),那么是的,编译器会根据它认为合适的将它们分配到寄存器或堆栈中。
编辑2:看起来,调用约定是特定于架构的,MIPS将通过堆栈中的前四个参数,正如Richard Pennington在他的回答中所述。所以你的情况,你不必指定额外的属性(这实际上是一个特定的x86属性。)
编译器会优化。尝试使用'gcc -fverbose-asm -O2 -S yoursource.c'然后在'yoursource.s'里面查看'yoursource.s' – 2012-10-12 05:59:41