GCC内联汇编错误:错误:表达式后的垃圾`(%esp)'

时间:2012-12-13 09:29:30

标签: gcc assembly inline-assembly

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代码尝试访问输入/输出操作数,则直接在内存中访问它们。这是对的吗?

非常感谢。

1 个答案:

答案 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;

}