3

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: Error: junk `(%esp)' after expression

如果我将“r”用于输入/输出约束,则代码将起作用。但我无法理解它为什么起作用以及错误代表什么。谁能告诉我?据我所知,'m' 只是告诉 gcc 不要分配寄存器,而是直接在内存中访问它们,如果内联 asm 代码尝试访问输入/输出操作数。这个对吗?

非常感谢。

4

1 回答 1

4

%0这里的问题是 GCC 为和生成 AT %1& T 语法结构%2。如果您查看生成的程序集,它看起来像:

.intel_syntax
mov eax, 8(%ebp)
mov edx, 12(%ebp)
add eax, edx
mov -4(%ebp), eax

这不是有效的 Intel 语法。

通常,您不需要在内联汇编中包含显式加载/存储操作 - 只需指定寄存器约束,编译器将自行生成加载/存储。这样做的好处是,即使您的变量(参数、本地变量)根本不驻留在内存中,而是在寄存器中,您的代码仍然是正确的 - 与您明确将内存加载/存储放在那里的情况不同。

对于您的示例,请尝试以下代码,查看程序集 ( 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;

}

于 2012-12-13T10:47:19.723 回答