2013-12-11 120 views
1

在網上找到的gcc內聯彙編示例中,我看到有時引用的寄存器名稱有時只有一個%,其他時間有兩個(即%%)。目前尚不清楚何時使用 單個%以及何時使用%%。 例如請看下面的例子。內聯彙編:註冊引用約定

/* Do b = a */ 

    int a=10, b; 

    asm ("movl %1, %%eax;\n" 
     "movl %%eax, %0;" 
     : "=r" (b)  /* output */ 
     : "r" (a)   /* input */ 
     : "%eax"   /* clobbered register */ 
     ); 

它採用%%前綴EAX寄存器這個例子編譯我的x86機器(完成RedHat 5.6(Tikanga 2.6.18-238.5.1.el5 x86_64的,2.6.18內核,GCC 4.7.2)的罰款。但是,下面的一行代碼

asm ("movl %%ecx, %%eax"); 

產生下面的錯誤。

a.c: Assembler messages: 

a.c:14: Error: bad register name `%%ecx' 

可能有人請扔在何時使用%一些光,當t o使用%%

謝謝。

+0

您一定要閱讀http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html –

回答

4

asm的主體(即實際代碼所在的部分)內部,使用%1,%2等來引用inline-asm塊的參數。 inline-asm將%視爲此用途的特殊字符。

恰巧,用於x86 GNU彙編語法也使用%作爲針對x86寄存器名稱(%eax%ebx等)的前綴。但是,因爲inline-asm爲%分配了不同的含義,所以必須將該塊中的%翻倍才能將其轉義。這就是爲什麼你會看到movl %1, %%eax:第一個%1擴展爲參數,%%eax前面的%%被替換爲單個%,導致%eax在編譯器的最終彙編輸出中。

在代碼塊之後的其他字符串中,%不再具有此特殊含義。這就是爲什麼在clobber列表中,例如,您只需要說%eax

在第二個示例中,內聯彙編程序沒有參數。沒有%1 ...替換說明符,因此您不需要將%加倍。

清澈如泥?

+1

感謝Joe Z,Rob Starling和elyashiv。我讀過Rob Starling提到的頁面,但它沒有解釋這個%Vs %%的差異以及Joe Z的解釋。在閱讀Joe Z的解釋之後,現在已經很清楚了。再次感謝Joe Z. – LML

+0

@ user3017124請考慮接受答案。在Stackoverflow,我們不會說謝謝;我們接受並贊成答案。 – Ali