2011-10-27 39 views
0

我創造了這個代碼:在Linux上使用GCC(v4.4.5,不優化)GCC增加了怪異的時間變量

#include <stdio.h> 

typedef unsigned int uint; 
uint in[2]={1,2},out[2]={3,4}; 

int main() { 

    in[0]=out[0]/10; 
} 

並編譯它,將所得的組件:

0000000000400474 <main>: 
400474:  55      push rbp 
400475:  48 89 e5    mov rbp,rsp 
400478:  8b 05 ae 03 20 00  mov eax,DWORD PTR [rip+0x2003ae]  # 0082c <out> 
40047e:  89 45 fc    mov DWORD PTR [rbp-0x4],eax 
400481:  ba cd cc cc cc   mov edx,0xcccccccd 
400486:  8b 45 fc    mov eax,DWORD PTR [rbp-0x4] 
400489:  f7 e2     mul edx 
40048b:  89 d0     mov eax,edx 
40048d:  c1 e8 03    shr eax,0x3 
400490:  89 05 8e 03 20 00  mov DWORD PTR [rip+0x20038e],eax  # 600824 <in> 
400496:  c9      leave 
400497:  c3      ret 
400498:  90      nop 
400499:  90      nop 
40049a:  90      nop 
40049b:  90      nop 
40049c:  90      nop 
40049d:  90      nop 
40049e:  90      nop 
40049f:  90      nop 

現在,問題是:這段代碼在第5行上做了什麼?

40047e:  89 45 fc    mov DWORD PTR [rbp-0x4],eax 

是不是存儲它從內存中的某個地方再次得到的值[0]?爲什麼這樣?我沒有告訴它立即讀取和寫入某個位置。

現在,這個時間變量的地址400486再次出現上線#7:

400486:  8b 45 fc    mov eax,DWORD PTR [rbp-0x4] 

它看起來就像這個例子GCC是產生非常低效的代碼,它會驅逐,因爲這些高速緩存行暫時存儲。請確認,也許有一些我沒有得到。

+7

那麼,你沒有說優化。 –

+2

當然,它產生的代碼效率低下;你告訴它不要優化。 – Dave

+1

堆棧不是'rbp-0x4'嗎?它以前使用'mov rbp,rsp'。 –

回答

5

當在-O0上編譯時,GCC會產生非常低效的代碼 - 您所看到的基本上是其程序內部表示的原始轉換。這種內部表示包含許多臨時變量,而您的加載/存儲對是通過這種臨時性的值。在較高的優化級別上,這些無用的加載/存儲將大部分被消除;然而在-O0上,即使最簡單的分析也是禁用的。

+0

我猜它的IL必須是基於堆棧的機器;我添加了'return argc;',並在返回之前將argc複製到了堆棧。 (我也嘗試過對簡單變量進行修改,並將'(1 << 32)* 0.8'複製到堆棧中。)甚至在'/ Od'處進行比較,MSVC編譯器通常會發出'mov eax,_out'' xor edx,edx''mov ecx,10''div ecx''mov _in,eax'。 (在'/ O2'上使用mul) – Neil

+1

@Neil:GCC有幾種不同的中間表示形式:GIMPLE,SSA,RTL,......當然,SSA表單創建了大量的臨時變量。 – ninjalj

+0

謝謝我明白了。我一直在想,GCC生成的原始代碼將完成即使使用-O0也要做的事情,而不是保存和恢復寄存器值。 – Nulik