2015-02-05 30 views
0

我這個小C代碼函數參數加載到寄存器在x64

void decode(int *xp,int *yp,int *zp) 
{ 
     int a,b,c; 
     a=*yp; 
     b=*zp; 
     c=*xp; 
     *yp=c; 
     *zp=a; 
     *xp=b; 
} 

然後我編譯它使用gcc -c -O1 decode.c到目標文件,然後傾倒對象與objdump的-M英特爾-d decode.o與此等價的彙編代碼

mov ecx,DWORD PTR [rsi] 
mov eax,DWORD PTR [rdx] 
mov r8d,DWORD PTR [rdi] 
mov DWORD PTR [rsi],r8d 
mov DWORD PTR [rdx],ecx 
mov DWORD PTR [rdi],eax 
ret 

而且我注意到,它不使用堆棧在all.But首先值仍然需要加載到寄存器。所以我的問題是如何將參數加載到寄存器中?編譯器會自動將參數加載到幕後的寄存器中嗎?或其他事情發生?,因爲沒有將參數加載到寄存器的指令。


而且有點偏離主題。當您爲編譯原始源代碼和機器代碼之間的關係而增加優化時,會降低機器代碼與源代碼的關聯度。默認情況下,如果你不指定GCC的優化標誌,它不會優化代碼。所以我試圖在沒有任何優化的情況下進行編譯以獲得源代碼的預期結果,但是我得到的是機器代碼的4-5倍,與源代碼無關並且可以理解。但是當我應用1級優化時,代碼看起來是可以理解的並且與源相關。但爲什麼?

+1

http://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI – EOF 2015-02-05 18:00:56

+0

不要一次提出兩個問題。 – 2015-02-05 18:06:23

+0

@EOF是的我知道,前6個int或ptr參數被傳遞給寄存器。但我不明白如何?我的意思是寄存器不能填滿空氣中的數據,傳遞必須轉化爲一些機器代碼,否則我失去了一些可怕的東西? – BsD 2015-02-05 18:06:28

回答

0

參數被加載到調用者的寄存器中。例如:

int a; 
int b; 

int f(int, int); 

int g(void) { 
    return f(a, b); 
} 

看爲g生成的代碼:

$ gcc -O1 -S t.c 
$ cat t.s 
… 
movl b(%rip), %esi 
movl a(%rip), %edi 
call f 

第二個問題:

所以我試圖編譯沒有任何優化,以獲得從源頭預期的結果,但我所得到的是機器代碼的4-5倍,與源代碼無關並且可以理解。

發生這種情況是因爲未優化的代碼很愚蠢。它是一種中間表示的直接轉換,其中即使不需要每個變量都存儲在堆棧中,即使不需要某個轉換,也可以通過顯式操作來表示每個轉換,等等。 -O1是讀取生成的程序集的最佳優化級別。也可以禁用幀指針,這可以將簡單函數的開銷降至最低。

+0

我寫了主要測試程序{int a,b,c;解碼(&a,&b,&c);}但是當我從objdump查看主機代碼時,它所做的只是一些奇怪的指令retz ret而沒有其他任何東西。你是什麼意思? – BsD 2015-02-05 21:22:11

+1

@ simple16最有可能的是你的函數'decode'被內聯到內部'main'。爲了讓你成爲一個例子,我不得不刪除'f'的實現,否則GCC會保持內聯。如果這不能解釋它,那麼請提出一個新問題。 – 2015-02-05 21:39:23

+0

它是有道理的。我還注意到沒有代碼將本地變量加載到寄存器。編譯器管理變量到寄存器的分配? – BsD 2015-02-06 13:11:46

相關問題