2011-01-28 49 views
1



我試圖使用內聯彙編器在代碼段中嵌入指向字符串的指針。但是gcc在符號名稱的開頭添加了一個$,導致鏈接錯誤。

這裏是一個小例子,gcc inline asm嵌入指向.rodata in .text,x86的指針

static const char str[] = "bar"; 
int main() 
{ 
    __asm__ __volatile__ 
    (
     "jmp 0f\n\t" 
     ".long %0\n\t" 
     "0:" 
     : 
     : "i" (str) 
    ); 
    return 0; 
} 

建築

gcc -Wall -save-temps test.c -o test 

給出了錯誤

test.o: In function `main': 
test.c:(.text+0x6): undefined reference to `$str' 

看.S臨時文件,可以看到前置爲str額外$

.file "test.c" 
    .section .rodata 
    .type str, @object 
    .size str, 4 
str: 
    .string "bar" 
    .text 
.globl main 
    .type main, @function 
main: 
.LFB0: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    movq %rsp, %rbp 
    .cfi_offset 6, -16 
    .cfi_def_cfa_register 6 
#APP 
# 4 "test.c" 1 
    jmp 0f 
    .long $str 
    0: 
# 0 "" 2 
#NO_APP 
    movl $0, %eax 
    leave 
    ret 
    .cfi_endproc 
.LFE0: 
    .size main, .-main 
    .ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5" 
    .section .note.GNU-stack,"",@progbits 

覺得我是這樣做的正確的方式,因爲同樣的方法適用於PPC GCC,

<clip> 
    b  0f 
    .long str 
    0: 
</clip> 

話又說回來,也許它僅僅是「運氣」,它適用於PPC。問題是因爲在使用AT & T synax時,$被用作立即數的前綴?

在這個簡單的例子中,我可以通過對內聯彙編程序中的符號名「str」進行硬編碼來解決這個問題,但真的需要它作爲內聯彙編程序的輸入約束。

有沒有人有任何想法如何讓這個工作在x86目標上?

感謝,
盧克 -

回答

0

同樣的事情發生使用鐺,可能是因爲代碼生成器不知道操作數是在使用。長期而不是一個立即指令操作數兵。你的代碼嘗試類似:

const char str[] = "bar"; 
#define string(str) __asm__ __volatile__ \ 
(\ 
    "jmp 0f\n\t" \ 
    ".long " #str "\n\t" \ 
    "0:" \       
) 
int main() 
{  
string(str); 
return 0; 
} 

(我不得不因爲編譯器優化,它不被引用刪除「靜態」的海峽。)

+0

這並不解決我張貼的例子,但不是實際使用情況不幸。實際上是使用__FILE__等,因此gcc正在生成像.LC0這樣的臨時符號,然後出現鏈接錯誤,尋找$ .LC0。希望避免在宏中生成符號名稱,以避免可能的衝突(即使使用__LINE__也是如此)。想想我剛剛找到了一個解決方案,雖然...因爲AT&T語法而添加了$,添加了-masm = intel可以正常工作。謝謝你看看這個理查德,非常感謝。 – 2011-01-28 11:24:05