Отказ от ответственности: я не знаю 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 будет передавать первые четыре аргумента в стеке, как заявил Ричард Пеннингтон в своем ответе. Таким образом, в вашем случае вам не нужно указывать дополнительный атрибут (который на самом деле является атрибутом, специфичным для x86).
person
int3
schedule
02.12.2009
gcc -fverbose-asm -O2 -S yoursource.c
, а затем загляните внутрьyoursource.s
- person Basile Starynkevitch   schedule 12.10.2012