[x86 inline asm]: width of register arguments

Andrew Haley aph@redhat.com
Sat Jun 29 16:10:00 GMT 2019


On 6/24/19 1:19 PM, Zdenek Sojka wrote:
> how does gcc choose the register arguments of an inline assembler and what
> can I assume about the "unused" bits?

The choice is made by the register allocator.

You can't assume anything about the "unused" bits. The "r" register
constraint means you get a whole register to use, of the wordsize of
the machine.

> My questions target the 64bit x86 architecture; I assume the behavior is the
> same for all target triplets x86_64-*-*
> 1) does gcc always use register of size matching the size of the variable?


> 2) can I assume anything about the high-order bits of the register? can I 
> overwrite them freely?

No; yes.

> 2a) does gcc use the "high" 8bit registers (ah, bh, ch, dh) for variable 
> allocation?


> 2b) can gcc allocate different 8bit variables in the "low" and "high"
> registers (eg. al/ah, bl/bh, ...)?
> For variables of type:
> uint8_t a8, b8;
> uint16_t a16, b16;
> ...

I think not, but I'm unsure.

> Enforcing same-sized arguments:
> a)
> __asm__ ("movb %b1, %b0" : "=r"(a8) : "r"(b8));
> or
> __asm__ ("movq %q1, %q0" : "=r"(a8) : "r"(b8));
> is always safe to do? (eg. moving 56bits of garbage won't hurt anything)
> OR might gcc assume something about the high-order 56bits (eg. zero, sign-/
> zero-extension of the lower 8 bits), which might get broken by the move?

If you ask for a register with the "r" constraint, all of that
register is yours to use.

> Assuming zero-extension:
> __asm__ ("movw %w1, %w0" : "=r"(a16) : "r"((uint8_t)b16));
> or
> __asm__ ("movw %w1, %w0" : "=r"(a16) : "r"(b8));
> does not seem to work (high-order 8 bits of a16 are garbage)

That's how x86 works.

Andrew Haley  (he/him)
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671

More information about the Gcc-help mailing list