Linux assembler error "impossible constraint in ‘asm’"
Solution 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.
Solution 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;
}
slashmais
Updated on February 01, 2020Comments
-
slashmais over 4 years
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. -
slashmais over 14 yearsThat works, thanks. Seems it doesn't like the 'modified' clause anymore, so I guess I'll have to push & popl whatever I change.
-
Stephen Canon over 14 yearsThe modified clause still works; I think the problem is that "output" implicitly specifies "modified" as well, so having eax represented in both field was causing the issue.
-
Daniel Kamil Kozar almost 9 yearsThis isn't very good advice. You're specifying the registers to be used in input and output lists, but still use hardcoded registers inside the actual assembly block. You should be using
%0
and%1
instead. -
Rahul Sreeram almost 9 years@DanielKamilKozar: The accepted answer had everything in a single line. So, I used the same/similar code to show how to do it in multiline. I didnt try to modify the hardcoded registers used in the original accepted answer as I thought it will be easier to understand when one compares the multi line to single.