11

我从 Linux 下的汇编程序开始。我已将以下代码保存为 testasm.c
并使用以下代码对其进行编译: gcc testasm.c -otestasm
编译器回复:“'asm' 中的不可能约束”。

#include <stdio.h>
int main(void)
{
    int foo=10,bar=15;

    __asm__ __volatile__ ("addl %%ebx,%%eax"
        : "=eax"(foo) 
        : "eax"(foo), "ebx"(bar) 
        : "eax" 
    );

    printf("foo = %d", foo);

    return 0;
}

我该如何解决这个问题?(我从这里复制了这个例子。)

Debian Lenny,内核 2.6.26-2-amd64
gcc 版本 4.3.2 (Debian 4.3.2-1.1)

解决方案
查看接受的答案 - 似乎不再支持“修改”子句。

4

3 回答 3

10
__asm__ __volatile__ ("addl %%ebx,%%eax" : "=a"(foo) : "a"(foo), "b"(bar));

似乎工作。我相信寄存器约束的语法在某些时候发生了变化,但它并没有很好的记录。我发现编写原始程序集更容易并避免麻烦。

于 2009-09-25T17:28:31.293 回答
7

约束是单个字母(可能带有额外的装饰),您可以指定几个替代项(即,中间操作数或寄存器是“ir”)。因此,约束“eax”表示约束“e”(有符号的 32 位整数常量)、“a”(寄存器 eax)或“x”(任何 SSE 寄存器)。这与 OP 的含义有点不同......并且输出到“e”显然没有任何意义。此外,如果某个操作数(在这种情况下是输入和输出)必须与另一个相同,则可以通过数字约束来引用它。没有必要说 eax 会被破坏,它是一个输出。您可以通过 %0, %1, ... 引用内联代码中的参数,无需使用显式寄存器名称。

#include <stdio.h>

int main(void)
{
    int foo=10, bar=15;

    __asm__ __volatile__ (
        "addl %2, %0"
        : "=a" (foo)
        : "0" (foo), "b" (bar)
    );

    printf("foo = %d", foo);

    return 0;
}

一个更好的解决方案是允许 %2 是任何东西,而 %0 是一个寄存器(因为 x86 允许,但你必须检查你的机器手册):

#include <stdio.h>

int main(void)
{
    int foo=10, bar=15;

    __asm__ __volatile__ (
        "addl %2, %0"
        : "=r" (foo)
        : "0" (foo), "g" (bar)
    );

    printf("foo = %d", foo);

    return 0;
}
于 2013-01-31T16:05:16.897 回答
0

如果一个人想使用多线,那么这也将工作..

  __asm__ __volatile__ (
        "addl %%ebx,%%eax; \
         addl %%eax, %%eax;" 
        : "=a"(foo) 
        : "a"(foo), "b"(bar)
    );

应该添加 '\' 以使编译器接受多行字符串(指令)。

于 2010-01-21T22:42:18.323 回答