GCC内联汇编错误:错误:表达式
后的垃圾邮件`(%esp)'我正在研究gcc内联汇编。我的环境是Win 7 32bit,mingw-gcc 4.6.1。
我遇到了关于'm'约束的问题。这是我的c函数代码:
static int asm_test(int a, int b)
{
int c = 0;
__asm__ __volatile__(".intel_syntax\n"
"mov eax, %1\n" //error
"mov edx, %2\n" //error
"add eax, edx\n"
"mov %0, eax\n" //error
".att_syntax"
:"=m"(c)\
:"m"(a),"m"(b)\
:"eax","edx"
);
return c;
}
对于at& t代码,它是这样的:
static int asm_test(int a, int b)
{
int c = 0;
__asm__ __volatile__(
"movl %1, $eax\n" //error
"movl %2, $edx\n" //error
"addl $edx, $eax\n"
"movl $eax, %0\n" //error
:"=m"(c)\
:"m"(a),"m"(b)\
:"eax","edx"
);
return c;
}
对于操作输入/输出操作数的三行中的每一行,gcc在编译时都会产生错误,如下所示:
C:\ Users \ farta \ AppData \ Local \ Temp \ cc99HxYj.s:22:错误:表达后的垃圾`(%esp)'
如果我使用'r'作为输入/输出约束,代码将起作用。但我无法理解为什么它有效以及错误代表什么。有人能告诉我吗?据我所知,'m'只是告诉gcc不分配寄存器,但如果内联asm代码尝试访问输入/输出操作数,则直接在内存中访问它们。这是对的吗?
非常感谢。
答案 0 :(得分:4)
这里的问题是GCC为%0
,%1
和%2
生成AT& T语法结构。如果查看生成的程序集,它看起来像:
.intel_syntax
mov eax, 8(%ebp)
mov edx, 12(%ebp)
add eax, edx
mov -4(%ebp), eax
这不是有效的英特尔语法。
通常,您不需要在内联汇编中包含显式加载/存储操作 - 只需指定寄存器约束,编译器将自行生成加载/存储。这样做的好处是,即使您的变量(参数,本地)根本不在内存中,但在寄存器中,您的代码仍然是正确的 - 与您明确将内存加载/存储放在那里的情况不同。
对于您的示例,请尝试以下代码,查看程序集(gcc -S
)并注意编译器将如何执行从参数区域(例如x86上的堆栈)的移动。
int asm_test(int a, int b)
{
__asm__ __volatile__ (
".intel_syntax\n"
"add %0, %1 \n"
".att_syntax \n"
:"+r"(a)
:"r"(b));
return a;
}