[英]Labels in GCC inline assembly
在我正在進行的GCC內聯匯編實驗中,我遇到了一個關於標簽和內聯代碼的新問題。
考慮以下簡單的跳轉:
__asm__
(
"jmp out;"
"out:;"
:
:
);
這確實沒有什么不同之處跳轉到out
標簽。 這樣,這段代碼編譯得很好。 但是如果你把它放在一個函數中,然后用優化標志進行編譯,編譯器就會抱怨:“錯誤:符號'out'已經被定義了”。
似乎正在發生的事情是編譯器每次內聯函數時都會重復此匯編代碼。 這使標簽out
得到復制,導致多out
的標簽。
那么,我該如何解決這個問題呢? 在內聯裝配中是否真的不可能使用標簽? 關於GCC內聯匯編的本教程提到:
因此,您可以將匯編放入CPP宏和內聯C函數中,因此任何人都可以將其用作任何C函數/宏。 內聯函數非常類似於宏,但有時使用起來更干凈。 請注意,在所有這些情況下,代碼將被復制,因此只應在該asm代碼中定義本地標簽 (1:樣式)。
我試圖找到有關這些“本地標簽”的更多信息,但似乎找不到與內聯匯編有關的任何內容。 看起來教程是說本地標簽是一個數字,后跟冒號(如1:
:),所以我嘗試使用這樣的標簽。 有趣的是,代碼已編譯,但在運行時它只是觸發了分段錯誤。 嗯...
那么任何建議,提示,答案......?
本地標簽的聲明確實是一個數字后跟冒號。 但是對本地標簽的引用需要后綴為f
或b
,具體取決於您是要向前還是向后 - 即1f
指向前進方向的下一個1:
標簽。
因此將標簽聲明為1:
是正確的; 但要引用它,你需要說jmp 1f
(因為你在這種情況下是向前跳)。
嗯,這個問題並沒有變得更年輕,但還有另外兩個有趣的解決方案。
1)此示例使用%=。 匯編程序模板中的%=被替換為“對整個編譯中的每個insn唯一的數字。這對於制作在給定insn中多次引用的本地標簽很有用。” 請注意,要使用%=,您(顯然)必須至少有一個輸入(盡管您可能不必實際使用它)。
int a = 3;
asm (
"test %0\n\t"
"jnz to_here%=\n\t"
"jz to_there%=\n\t"
"to_here%=:\n\t"
"to_there%=:"
::"r" (a));
這輸出:
test %eax
jnz to_here14
jz to_there14
to_here14:
to_there14:
或者,您可以使用asm goto(我認為在v4.5中添加)。 這實際上允許您跳轉到c標簽而不僅僅是asm標簽:
asm goto ("jmp %l0\n"
: /* no output */
: /* no input */
: /* no clobber */
: gofurther);
printf("Didn't jump\n");
// c label:
gofurther:
printf("Jumped\n");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.