編譯器不運行代碼(除非它執行幾輪分析和更好的代碼執行),但它必須準備它 - 這包括如何保持程序定義的變量,是否使用快速和作爲寄存器的高效存儲,或者使用較慢(並且更易於產生副作用)的內存。
最初,您的本地變量將被簡單地分配到堆棧幀的位置(當然除了您明確使用動態分配的內存外)。如果你的函數分配了一個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