编译器不运行代码(除非它执行几轮分析和更好的代码执行),但它必须准备它 - 这包括如何保持程序定义的变量,是否使用快速和作为寄存器的高效存储,或者使用较慢(并且更易于产生副作用)的内存。
最初,您的本地变量将被简单地分配到堆栈帧的位置(当然除了您明确使用动态分配的内存外)。如果你的函数分配了一个int,你的编译器可能会告诉堆栈增加几个额外的字节,并使用该存储器地址来存储该变量并将其作为操作数传递给代码正在对该变量进行的任何操作。但是,由于内存速度较慢(即使在缓存时),并且操作它会对CPU造成更多限制,但在稍后的阶段,编译器可能会决定尝试将某些变量移入寄存器。这种分配是通过一种复杂的算法完成的,该算法试图选择能够适应现有逻辑寄存器数量的最重用和等待时间的关键变量(同时确认了各种限制,例如某些指令要求操作数存在于该登记册)。
还有一个复杂因素 - 一些内存地址可能会在编译时未知的方式与外部指针混淆,在这种情况下,您无法将它们移动到寄存器中。编译器通常是一个非常谨慎的一群,他们中的大多数会避免危险的优化(否则他们需要进行一些特殊的检查以避免令人讨厌的事情)。
毕竟是,编译器仍然不够礼貌让你建议哪个变量是重要的,你的关键,如果他错过了它,并通过与register
关键字你基本上要他这些标记尝试通过使用寄存器来优化此变量,只要有足够的寄存器可用并且不会出现混叠。
这里有一个小例子:看看下面的代码,做同样的事情两次,但略有不同的情况:
#include "stdio.h"
int j;
int main() {
int i;
for (i = 0; i < 100; ++i) {
printf ("i'm here to prevent the loop from being optimized\n");
}
for (j = 0; j < 100; ++j) {
printf ("me too\n");
}
}
请注意,我是本地的,J是全球性的(因此编译器没有按”不知道其他人是否可以在运行期间访问他)。
在GCC编译与-O3产生以下代码为主要:
0000000000400540 <main>:
400540: 53 push %rbx
400541: bf 88 06 40 00 mov $0x400688,%edi
400546: bb 01 00 00 00 mov $0x1,%ebx
40054b: e8 18 ff ff ff callq 400468 <[email protected]>
400550: bf 88 06 40 00 mov $0x400688,%edi
400555: 83 c3 01 add $0x1,%ebx # <-- i++
400558: e8 0b ff ff ff callq 400468 <[email protected]>
40055d: 83 fb 64 cmp $0x64,%ebx
400560: 75 ee jne 400550 <main+0x10>
400562: c7 05 80 04 10 00 00 movl $0x0,1049728(%rip) # 5009ec <j>
400569: 00 00 00
40056c: bf c0 06 40 00 mov $0x4006c0,%edi
400571: e8 f2 fe ff ff callq 400468 <[email protected]>
400576: 8b 05 70 04 10 00 mov 1049712(%rip),%eax # 5009ec <j> (loads j)
40057c: 83 c0 01 add $0x1,%eax # <-- j++
40057f: 83 f8 63 cmp $0x63,%eax
400582: 89 05 64 04 10 00 mov %eax,1049700(%rip) # 5009ec <j> (stores j back)
400588: 7e e2 jle 40056c <main+0x2c>
40058a: 5b pop %rbx
40058b: c3 retq
正如你可以看到,第一循环计数器坐在EBX,和递增在每次迭代并抵靠限制进行比较。
然而,第二个循环是危险的,gcc决定通过内存传递索引计数器(每次迭代将其加载到rax中)。这个例子用来说明使用寄存器时会有多好,以及有时候不能。
我不明白你在问什么。变量必须在寄存器中才能执行指令。这正是CPU工作的方式。 – Kevin
目前还不清楚你究竟在问什么。您正在阅读的文档讨论编译器生成的代码。即来自您的C代码,编译器需要生成告诉CPU如何操作的代码,其中包括变量驻留在内存中的位置,执行指令时使用哪个CPU寄存器等等。一旦编译器生成了该代码,就会在运行编译代码时发生实际的内存/寄存器分配和使用。 – nos