Linux assembler error “impossible constraint in ‘asm’”

做~自己de王妃 提交于 2019-12-04 00:24:33

问题


I'm starting with assembler under Linux. I have saved the following code as testasm.c
and compiled it with: gcc testasm.c -otestasm
The compiler replies: "impossible constraint in ‘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;
}

How can I resolve this problem? (I've copied the example from here.)

Debian Lenny, kernel 2.6.26-2-amd64
gcc version 4.3.2 (Debian 4.3.2-1.1)

Resolution:
See the accepted answer - it seems the 'modified' clause is not supported any more.


回答1:


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

seems to work. I believe that the syntax for register constraints changed at some point, but it's not terribly well documented. I find it easier to write raw assembly and avoid the hassle.




回答2:


The constraints are single letters (possibly with extra decorations), and you can specify several alternatives (i.e., an inmediate operand or register is "ir"). So the constraint "eax" means constraints "e" (signed 32-bit integer constant), "a" (register eax), or "x" (any SSE register). That is a bit different that what OP meant... and output to an "e" clearly doesn't make any sense. Also, if some operand (in this case an input and an output) must be the same as another, you refer to it by a number constraint. There is no need to say eax will be clobbered, it is an output. You can refer to the arguments in the inline code by %0, %1, ..., no need to use explicit register names. So the correct version for the code as intended by OP would be:

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

A better solution would be to allow %2 to be anything, and %0 a register (as x86 allows, but you'd have to check your machine manual):

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



回答3:


If one wants to use multiline, then this will also work..

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

'\' should be added for the compiler to accept a multiline string (the instructions).



来源:https://stackoverflow.com/questions/1478513/linux-assembler-error-impossible-constraint-in-asm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!