2013-07-07 45 views
0

如果我不在clobber列表中寫任何東西,gcc編譯器是否使用push/pop來進行註冊備份?輸入和輸出列表寄存器會發生什麼?G ++ Asm內聯:註冊破解

我將做一個簡短的asm內聯,它將一些通用寄存器保存到XMM/YMM寄存器,然後在通用寄存器上播放。最後,原始值從XMM/YMM寄存器返回到通用目錄。編譯器會把push/pops保存嗎?

我怎麼能告訴GCC編譯器:「不要爲我推/流行enything,我使用XMM/YMM爲目的也許我會做俯臥撐/彈出自己」

喜歡的東西:

__asm__ __volatile__ (
     ".intel_syntax noprefix \n\t" 
     "movd xmm0,eax \n\t"//storing in xmm registers instead of pushing 
     "movd xmm1,ebx \n\t" 
     "movd xmm2,ecx \n\t" 
     "movd xmm3,edx \n\t" 
     "movd xmm4,edi \n\t" // end of backups 
     //. 
     //... doing work 
     //. 
     "movd edi,xmm4 \n\t" 
     "movd edx,xmm3 \n\t" 
     "movd ecx,xmm2 \n\t" 
     "movd ebx,xmm1 \n\t" 
     "movd eax,xmm0 \n\t" // end of pops 

     ://outputs 
     "=g"(x[0]), //%0 
     "=g"(x[1]) //%1 
     ://inputs 
     "g"(x[0]), //%2 
     "g"(x[1]) //%3 
     ://no clobber list 
    ); 

或像這樣(我知道這個交換是極其緩慢的,只是想有推持久性有機污染物的工作):

__asm__ __volatile__ (
     ".intel_syntax noprefix \n\t" 
     "push rax \n\t" 
     "push rbx \n\t" 
     "push rcx \n\t" 
     "push rdx \n\t" 

     "mov eax,%2 \n\t" 
     "mov ecx,%3 \n\t" 
     "mov edx,eax \n\t" 
     "mov eax,ecx \n\t" 
     "mov ecx,edx \n\t" 
     "mov %0,eax \n\t" 
     "mov %1,ecx \n\t" 

     "pop rdx \n\t" 
     "pop rcx \n\t" 
     "pop rbx \n\t" 
     "pop rax \n\t" 

     ://outputs 
     "=g"(x[0]), //%0 
     "=g"(x[1]) //%1 
     ://inputs 
     "g"(x[0]), //%2 
     "g"(x[1]) //%3 
     ://no clobber list 
    ); 
+0

編譯器要「擁有」 XMM暫存器就像普通通用的。除非您告訴編譯器,否則不能直接在內聯彙編中使用它們:您的內聯彙編期望XMM中的值作爲輸入/輸出操作數,或者:_explicitly_列出您希望在clobber list_中修改的reg。如果你這樣做,那麼你就沒有必要自己「推」/「流行」了。如果(且僅當)它選擇將任何變量放入您聲稱要修改的寄存器之一時,編譯器會自動在內聯asm語句之前/之後插入此類代碼。 –

+0

好的,我會將它們顯示爲「YMM0」,「YMM16」嗎?保存/恢復寄存器的開銷是否可能小於JNI調用的開銷? –

+0

是的,理論上你可以在clobber列表中列出所有矢量regs。但這是浪費的,可能是不必要的......它取決於你的確切用例,無論是內聯彙編程序還是完全獨立的函數,全編寫的彙編程序都更好。可以找到構建人造測試案例...需要更多地瞭解您要解決的實際問題。 –

回答

1

這個問題是怎麼樣的貓膩。據我所知,你編譯的方式會對結果產生影響。我不確定這是否是您需要的,但如果您不使用內聯彙編,則可以控制它。

您將代碼編寫在單獨的.s文件中,並使用-O3等優化進行編譯,gcc不會推送和保護非易失性寄存器。我自己不使用內聯彙編,所以我不清楚這一部分。你可以自己測試:D

順便說一句:我想如果你編寫.asm文件並使用nasm編譯它並將該對象與gcc鏈接,則會發生同樣的情況。通過優化,我不認爲gcc會自動執行push/pop。讓我知道我的回覆是否有問題。謝謝。

好運

xiangpisaiMM

+0

把C++連接到java(通過JNI和g ++編譯器)在我頭上(我幾乎沒有設法做到),現在你告訴我要把C++和assembly連接起來,就像是一樣:D。好的,會嘗試使用-O3。 –

+0

它工作! OMG -o3是一個優化,可以讓我在asm內嵌任何我想做的事情。 –

+0

單獨的'.s'文件與將內嵌相同代碼嵌入內聯彙編程序非常不同。首先,執行一個函數調用_tells the compiler_某些寄存器不能保證在函數調用返回時保留它們的值。代碼可能不會假定任何XMM regs或任何參數regs('RDI','RSI','RDX','RCX','R8'和'R9')或'RAX'都不被保留髮布「調用」指令。因此,如果你的彙編函數只使用其中的任何一個,那麼只要你有一個_separate函數,就不需要'push'/'pop'任何東西。 –