如果我不在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
);
編譯器要「擁有」 XMM暫存器就像普通通用的。除非您告訴編譯器,否則不能直接在內聯彙編中使用它們:您的內聯彙編期望XMM中的值作爲輸入/輸出操作數,或者:_explicitly_列出您希望在clobber list_中修改的reg。如果你這樣做,那麼你就沒有必要自己「推」/「流行」了。如果(且僅當)它選擇將任何變量放入您聲稱要修改的寄存器之一時,編譯器會自動在內聯asm語句之前/之後插入此類代碼。 –
好的,我會將它們顯示爲「YMM0」,「YMM16」嗎?保存/恢復寄存器的開銷是否可能小於JNI調用的開銷? –
是的,理論上你可以在clobber列表中列出所有矢量regs。但這是浪費的,可能是不必要的......它取決於你的確切用例,無論是內聯彙編程序還是完全獨立的函數,全編寫的彙編程序都更好。可以找到構建人造測試案例...需要更多地瞭解您要解決的實際問題。 –