术语“调用者保存的寄存器”和“被调用者保存的寄存器”分别是指函数调用者保存的寄存器和被调用函数保存的寄存器。什么寄存器取决于处理器架构和称为“ABI”(应用程序二进制接口)的规范 - 这因处理器系列而异,并且在操作系统之间也经常不同。但基本原则是编译器生成的机器码是有一定期望的:任何函数都可以自由使用R0、R1、R2,调用者必须期望这些在调用中被修改。R3-R6是被调用函数保存的,如果调用函数使用R7或R8,在调用任何函数之前都必须保存。[这是一个“任意处理器”,
所以要分析你的功能......
让我们首先分解这个函数:
int foo() {
int a = 1, b = 2, c = 3, w;
c = abs(c);
c = c + b + 7;
for (w = 0; w<10; w++) {
b += bar(b);
}
return c;
}
变量“a”未使用,因此可以删除。函数“abs”可以在编译时解析,因此可以删除该行。
c = c + b + 7;
可以在编译时解析为 2 + 3 + 7 = 12。我们只需将常量 12 移至 return 语句并去掉c
. 所以,现在我们剩下:
int foo() {
int b = 2, w;
for (w = 0; w<10; w++) {
b += bar(b);
}
return 12;
}
这至少使用了 2 个寄存器。
对下一个函数执行相同的操作:
int bar(int v) {
int a = 1, b = 2;
a += v + b;
printf(“v=%d\n”, v);
return v;
}
我们可以删除a = 1, b = 2
and a += v + b
,因为a
andb
没有被使用。这留下:
int bar(int v) {
printf(“v=%d\n”, v);
return v;
}
现在,一个聪明的编译器会内联bar
到 foo 中,现在我们得到:
int foo() {
int b = 2, w;
for (w = 0; w<10; w++) {
printf(“v=%d\n”, b);
b += b;
}
return 12;
}
实际上,这可以通过两个或三个寄存器来完成,加上需要做的任何事情printf
(我们无法真正说出那是什么......)。编译器很可能会再走一步并“展开”循环,在这种情况下,可能会再删除一个寄存器。