What is the correct use of multiple input and output operands in extended GCC asm under register constraint? Consider this minimal version of my problem. The following brief extended asm code in GCC, AT&T syntax:
int input0 = 10;
int input1 = 15;
int output0 = 0;
int output1 = 1;
asm volatile("mov %[input0], %[output0]\t\n"
"mov %[input1], %[output1]\t\n"
: [output0] "=r" (output0), [output1] "=r" (output1)
: [input0] "r" (input0), [input1] "r" (input1)
:);
printf("output0: %d\n", output0);
printf("output1: %d\n", output1);
The syntax appears correct based on https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html However, I must have overlooked something or be committing some trivial mistake that I for some reason can't see.
The output with GCC 5.3.0 p1.0 (no compiler arguments) is:
output0: 10
output1: 10
Expected output is:
output0: 10
output1: 15
Looking at it in GDB shows:
0x0000000000400581 <+43>: mov eax,DWORD PTR [rbp-0x10]
0x0000000000400584 <+46>: mov edx,DWORD PTR [rbp-0xc]
0x0000000000400587 <+49>: mov edx,eax
0x0000000000400589 <+51>: mov eax,edx
0x000000000040058b <+53>: mov DWORD PTR [rbp-0x8],edx
0x000000000040058e <+56>: mov DWORD PTR [rbp-0x4],eax
From what I can see it loads eax with input0 and edx with input1. It then overwrites edx with eax and eax with edx, making these equal. It then writes these back into output0 and output1.
If I use a memory constraint (=m) instead of a register constraint (=r) for the output, it gives the expected output and the assembly looks more reasonable.
=&r
for your output0 operand since that register is modified before the last instruction of your assembler template. GCC will think it can reuse that register as an input as well.&
will prevent the early clobber assigned register from being used as an input register – Michael Petchg
constraint on your input operands instead ofr
. Since the outputs are defined as registers only, and themov
instructions in your template can take at least one memory or immediate value operand you give the compiler a chance to perform other optimizations by usingg
.g
constraint is documented as Any register, memory or immediate integer operand is allowed, except for registers that are not general registers – Michael Petchg
as input operand constraints, the compiler should be able to realize that some of the inputs are in fact constants (immediate) values, which should allow for some code reduction. You can see these optimizations much better if you compile with GCC using an optimization level of-O3
– Michael Petch"=r,r,rm,rm", "=r,rm,r,rm" : "g,g,ri,ri", "g,ri,g,ri"
. – Ross Ridge