Haftungsausschluss: Ich weiß nicht, MIPS, aber ich habe einige x86 wissen, und ich denke, das Prinzip das gleiche sein sollte ..
In der üblichen Funktion Aufrufkonvention, drückt der Compiler den Wert n
auf den Stapel, um es an die Funktion foo
zu übergeben. Allerdings gibt es die fastcall
Konvention, die Sie verwenden können, um gcc mitzuteilen, den Wert stattdessen über die Register zu übergeben. (MSVC hat auch diese Option, aber ich bin mir nicht sicher, was die Syntax ist.
)
test.cpp:
int foo1 (int n) { return ++n; }
int foo2 (int n) __attribute__((fastcall));
int foo2 (int n) {
return ++n;
}
mit g++ -O3 -fomit-frame-pointer -c test.cpp
die oben Kompilieren, bekomme ich für foo1
:
mov eax,DWORD PTR [esp+0x4]
add eax,0x1
ret
Wie man sehen kann, liest er in dem Wert aus dem Stapel.
Und hier ist foo2
:
lea eax,[ecx+0x1]
ret
Nun nimmt sie den Wert direkt aus dem Register.
Natürlich, wenn Sie die Funktion inline, wird der Compiler eine einfache Ergänzung in den Körper Ihrer größeren Funktion, unabhängig von der von Ihnen angegebenen Aufrufkonvention. Aber wenn Sie es nicht inline bekommen können, wird dies passieren.
Disclaimer 2: Ich sage nicht, dass Sie den Compiler immer wieder erraten sollten. Es ist wahrscheinlich in den meisten Fällen nicht praktisch und notwendig. Aber gehen Sie nicht davon aus, dass es perfekten Code produziert.
Bearbeiten 1: Wenn Sie über einfache lokale Variablen sprechen (nicht Funktionsargumente), dann ja, wird der Compiler sie in den Registern oder auf dem Stapel zuweisen, wie es passt.
Bearbeiten 2: Es scheint, dass Aufrufkonvention architekturspezifisch ist, und MIPS wird die ersten vier Argumente auf dem Stapel übergeben, wie Richard Pennington in seiner Antwort angegeben hat. In diesem Fall müssen Sie das zusätzliche Attribut nicht angeben (das tatsächlich ein x86-spezifisches Attribut ist.)
Der Compiler würde optimieren. Versuchen Sie 'gcc -fverbose-asm -O2 -S yoursource.c' dann schauen Sie nach' yoursource.s' –