3

最近我在一次採訪中被問到了如下問題: 究竟誰確定寄存器變量將存儲在哪裏(在RAM或寄存器中)。誰決定實際存儲寄存器存儲類?

我已經在谷歌搜索,我得到了編譯器的決定。 但編譯器如何決定?根據我的理解,應該在運行時決定。

如果我們在不同的機器上編譯和運行程序,那麼編譯器如何決定在哪裏存儲寄存器存儲類的值呢?

+2

這是編譯時決定。當你寫這樣的東西 – marom

+0

寄存器int a,b,c; a = b + c編譯器必須知道在哪裏存儲a + b的結果。延遲運行時間的決定會使代碼變得更慢,因此使用寄存器 – marom

+0

沒有任何好處,假設編譯器決定將該變量存儲在寄存器中,但在運行時沒有可用的寄存器,所以值將存儲在內存中,那麼誰來決定呢?它是內核還是進程控制塊?或者是其他東西 ? –

回答

3

register存儲類說明是一個暗示給訪問一個變量的編譯器應該是「儘可能快」,這意味着(在寄存器體系結構),它的存儲應該分配給寄存器。這禁止了一些事情,比如採取變量寄存器的地址沒有地址。但是,編譯器可以自由地忽略此提示(§ 6.7.1 ¶ 5):儘可能快

用於與存儲類說明register一個對象的標識符的聲明表明,訪問對象是。這些建議的有效程度是由實施定義的。

編譯代碼時,編譯器必須選擇如何將局部變量和算術運算映射到CPU寄存器和堆棧內存的操作。這被稱爲寄存器分配;這些決定是在編譯時進行的,並且被編入一個函數的編譯代碼中。

假設我們有一個非常天真的編譯器,它完全符合我們所說的,並且不會優化任何東西。如果我們給它這樣的代碼:

int x; 
x = 2; 
x += 5; 

然後,我們可能會看到這樣的輸出,在x86機器上:

sub esp, 4   ; allocate stack space for an integer 
mov dword [esp], 2 
add dword [esp], 5 

但是,如果我們寫:

register int x; 
x = 2; 
x += 5; 

那麼我們可能會期望看到:

mov eax, 2 
add eax, 5 

後者我因爲它更喜歡通過內存訪問進行寄存器訪問。在實踐中,當代編譯器具有智能寄存器分配算法,使得這個存儲類標識符變得不必要。

+0

感謝您的解釋喬恩,如果我只是將我的a.out ftp到一些不同的機器(相同的操作系統),並在那裏運行,但編譯器已經做出了有關注冊一臺機器,在哪裏編譯程序,如果程序在不同的機器上運行將會怎樣?那時候它是如何決定存儲在寄存器或RAM中的呢? –

+0

@ pankajkushwaha:如果編譯器已將一個變量分配給一個寄存器,那麼它將被放置在任何運行該代碼的機器上的該寄存器中。架構(x86,x86-64,ARM等)定義了哪些寄存器可用 - 例如,每個x86處理器都有一個'eax'寄存器。 –

+0

好的,但如果該遠程機器寄存器已被使用,可能是由其他程序?(鑑於我的程序是在不同的機器上編譯的) –

1

編譯器會在編譯期間根據這些優化做出幾種類型的優化,請求被授予或拒絕。

彙編的第三最後階段---中間代碼生成繼續產生基於 編碼的中間三地址(操作碼),它是在編譯器 優化的倒數第二個階段進一步優化的基礎。編譯器的最後一個階段--- target code generation可以保證寄存器存儲 類變量是否被授予寄存器。

授予變量寄存器訪問的請求由程序進行,但最後,它是取決於誰決定在寄存器變量的內存分配,編譯器: -

  1. CPU中寄存器的可用性。

  2. 更穩定的優化等。

+0

好吧,我指的是以下行: - 目標 代碼生成可以保證寄存器存儲類變量是否被授予寄存器。但是如果我們在不同的機器上編譯和運行程序會發生什麼情況,假設在編譯時有足夠的寄存器可用,所以編譯決定存儲在寄存器中,但是當我們運行程序時,沒有可用的空閒寄存器,那麼數據將會被存儲在RAM中,所以我的意思是誰決定運行時間....我的理解錯誤? –

+0

@ pankajkushwaha-正如我已經提到的那樣,編譯器的工作是清除變量是否存儲在寄存器中。如果請求是由編譯器完成的,那麼在編譯時本身就可以準備好分配寄存器空間。 '如果編譯器分配一個寄存器,怎麼可能沒有寄存器availabe ??? –

+0

謝謝shekhar,我明白了你的觀點,我唯一的疑問就是如果我只是把我的a.out ftp到某個不同的機器上OS),並在那裏運行,但編譯器已經決定了程序編譯的機器的註冊,如果程序運行在不同的機器上會發生什麼? –