gcc内联asm在.text中嵌入指向.rodata的指针,x86
gcc内联asm在.text中嵌入指向.rodata的指针,x86,gcc,assembly,x86,inline-assembly,Gcc,Assembly,X86,Inline Assembly,我正在尝试使用内联汇编程序在代码段中嵌入一个指向字符串的指针。但是gcc在符号名的开头添加了$,导致了链接错误。下面是一个最小的示例 static const char str[] = "bar"; int main() { __asm__ __volatile__ ( "jmp 0f\n\t" ".long %0\n\t" "0:" : : "i" ( str ) ); re
我正在尝试使用内联汇编程序在代码段中嵌入一个指向字符串的指针。但是gcc在符号名的开头添加了$,导致了链接错误。
下面是一个最小的示例
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 temp文件,可以看到额外的$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>
b0f
.朗街
0:
再说一次,也许这只是“运气”,它对ppc有效。问题是否是因为在使用AT&T synax时,$被用作即时消息的前缀
在这个简单的示例中,我可以通过在内联汇编程序中硬编码符号名“str”来解决这个问题,但实际上需要将其作为内联汇编程序的输入约束
有人对如何在x86目标上实现这一点有什么想法吗
谢谢,-Luke使用clang时也会发生同样的情况,可能是因为代码生成器不知道操作数在.long中使用,而不是作为立即指令操作数。您可以尝试以下代码:
const char str[] = "bar";
#define string(str) __asm__ __volatile__ \
( \
"jmp 0f\n\t" \
".long " #str "\n\t" \
"0:" \
)
int main()
{
string(str);
return 0;
}
(我不得不删除str上的“static”,因为编译器将其优化为未被引用。)这确实修复了我发布的示例,但不幸的是没有修复实际用例。实际上正在使用文件等,所以gcc生成了.LC0之类的临时符号,然后在查找$.LC0时出现了链接错误。要避免在宏中生成符号名称,以避免可能的冲突(即使出现了行)。我想我刚刚找到了一个解决办法。。。由于AT&T语法,添加了$masm=intel,因此可以正确工作。谢谢你看这个Richard,非常感谢。