的CentOS 6.5 64位VPS,500MB RAM GCC 4.8.2爲什麼在這個內聯彙編中需要使用edi約束?
我有以下功能僅適用如果我使用EDI作爲約束來保存字符串指針。如果我嘗試使用任何其他寄存器或約束g
或q
等,它會發生段錯誤。
但是隻有當鏈接時間優化和o3
一起使用時纔會出現此問題。如果o2
沒關係。如果我不使用-flto
,那很好。但是,兩者一起,那麼唯一的註冊,我可以使用不崩潰是edi
gcc -flto
CFLAGS=-I. -flto -std=gnu11 -msse4.2 -fno-builtin-printf -Wall -Winline -Wstrict-aliasing -g -pg -O3 -lrt -lpthread
好像有可能是某種寄存器重挫事情還是其他什麼東西的。我真的很難理解爲什麼以及如何解決這個問題。另一個有趣的方面是生成的程序集使用指針之前將rdi
放入rdx
,但如果我嘗試使用任一寄存器作爲輸入約束......它會發生段錯誤!如果它在積極的編譯選項下失敗,它向我暗示編譯器會以某種方式填塞,或者更可能是我做錯了什麼。
char *sse4_strCRLF(char *str)
{
__m128i M = _mm_set1_epi8(13);
char *res;
__asm__ __volatile__(
"xor %0,%0\n\t"
"sub $1, %1\n\t"
"1:" "sub $15,%1\n\t"
".align 16\n\t"
"2:" "add $16, %1\n\t"
"pcmpistri $0x08,(%1),%2\n\t"
"ja 2b\n\t"
"jnc 2f\n\t"
"cmpb $10,1(%1,%%rcx)\n\t"
"jne 1b\n\t"
"add %%rcx,%1\n\t"
"mov %1,%0\n\t"
"2:"
:"=q"(res)
:"edi"(str),"x"(M) //<-- if use anything except edi, it segfaults
:"rcx"
);
return (char*) res;
}
拆輸出:
00000000000002e0 <sse4_strCRLF>:
2e0: 55 push rbp
2e1: 48 89 e5 mov rbp,rsp
2e4: e8 00 00 00 00 call 2e9 <sse4_strCRLF+0x9>
2e9: 66 0f 6f 05 00 00 00 00 movdqa xmm0,[rip+0x0] # 2f1 <sse4_strCRLF+0x11>
2f1: 48 89 fa mov rdx,rdi //<--- puts rdi into rdx!
2f4: 48 31 c0 xor rax,rax
2f7: 48 83 ea 01 sub rdx,0x1
2fb: 48 83 ea 0f sub rdx,0xf
2ff: 90 nop
300: 48 83 c2 10 add rdx,0x10
304: 66 0f 3a 63 02 08 pcmpistri xmm0,[rdx],0x8
30a: 77 f4 ja 300 <sse4_strCRLF+0x20>
30c: 73 0d jae 31b <sse4_strCRLF+0x3b>
30e: 80 7c 0a 01 0a cmp byte[rdx+rcx*1+0x1],0xa
313: 75 e6 jne 2fb <sse4_strCRLF+0x1b>
315: 48 01 ca add rdx,rcx
318: 48 89 d0 mov rax,rdx
31b: 5d pop rbp
31c: c3 ret
我不認爲「edi」是指你認爲它的作用。查看[docs](https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html)(向下滾動到x86系列):「e」表示「32位有符號整數常量」,「d 「表示rdx寄存器,」i「表示」立即整型操作數「。通過指定所有3,您允許編譯器在這3個選項中進行選擇,而不是(因爲我懷疑您打算)選擇edi寄存器。 –
另一個重要點:正如[docs](https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands)所說,您不得修改輸入參數。 –
我不知道禁止修改輸入參數!我認爲這會解決它,但唉。我改變了代碼,以便%1被移入一個寄存器,所有操作都在該寄存器上完成,但仍然是相同的問題 – poby