免责声明:我不知道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 特定的属性。)