我在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;
}
如何解决此问题? (我从here复制了这个例子。)
Debian Lenny,内核2.6.26-2-amd64
gcc版本4.3.2(Debian 4.3.2-1.1)
解决:
请参阅接受的答案 - 似乎不再支持'modified'子句。
答案 0 :(得分:9)
__asm__ __volatile__ ("addl %%ebx,%%eax" : "=a"(foo) : "a"(foo), "b"(bar));
似乎有效。我相信寄存器约束的语法在某些时候发生了变化,但它并没有很好的记录。我发现编写原始组件更容易,避免麻烦。
答案 1 :(得分:5)
约束是单个字母(可能带有额外的装饰),您可以指定几个备选方案(即,中间操作数或寄存器是“ir”)。因此约束“eax”表示约束“e”(带符号的32位整数常量),“a”(寄存器eax)或“x”(任何SSE寄存器)。这与OP的意思有点不同...... 输出到“e”显然没有任何意义。此外,如果某个操作数(在这种情况下是输入和输出)必须与另一个操作数相同,则通过数字约束来引用它。没有必要说eax会被破坏,它是一个输出。您可以通过%0,%1,...来引用内联代码中的参数,无需使用显式寄存器名称。因此,OP所预期的代码的正确版本将是:
#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;
}
答案 2 :(得分:0)
如果想要使用多线,那么这也会有效..
__asm__ __volatile__ (
"addl %%ebx,%%eax; \
addl %%eax, %%eax;"
: "=a"(foo)
: "a"(foo), "b"(bar)
);
应添加'\'以使编译器接受多行字符串(说明)。