当前位置:  开发笔记 > 运维 > 正文

Linux汇编程序错误"'asm'中不可能的约束"

如何解决《Linux汇编程序错误"'asm'中不可能的约束"》经验,为你挑选了2个好方法。

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

#include 
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)

解决方案:
查看已接受的答案 - 似乎不再支持'modified'子句.



1> Stephen Cano..:
__asm__ __volatile__ ("addl %%ebx,%%eax" : "=a"(foo) : "a"(foo), "b"(bar));

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


修改后的条款仍然有效; 我认为问题是"输出"也隐含地指定"已修改",因此在两个字段中都表示的eax导致了问题.

2> vonbrand..:

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

#include 

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 

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;
}

推荐阅读
落单鸟人
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有