Operands in gcc inline assembly

Some time ago I was struggling with gcc's inline assembly. I wanted to use the address of a function. "m" as a constraint didn't work. gcc said it's not directly addresseble. "i" worked, but not with "lea". In this case the assembler complained about invalid operand. No wonder, it produced something like "lea $function, %%eax". I read in the gcc manual. Nothing that helped me. I tried all constraints. It just didn't work. And now I found it. Not inthe gcc manual, but on another webpage (A Brief Tutorial on GCC inline asm (x86 biased)), when I was seeking something completely different.

The solution is to modify the way gcc translates the operands into strings. Where "%0" will give you the default represenstation of operand 0, you can modify it, by inserting a letter (like "%c0"). The ones that were accepted by gcc are: a,b,c,d,e,f,h,k,l,n,q,s,t,w,x,y,z, A,B,C,D,E,F,H,L,O,P,Q,S,T,W,X,Y. Some of them did nothing (d, X) others resulted in a compiler error (e, f, C, D, E, F, H). This is the rest:

  • %a0 - memory addressed by register operand 0
  • %A0 - operand 0 with a "*" prefix
  • %b0 - 8bit form of register operand 0 (al)
  • %B0 - gives "b"
  • %c0 - operand 0, without $ prefix
  • %h0 - high 8 bit form of register operand 0 (ah)
  • %k0 - 32bit form of register operand 0 (eax)
  • %l0 - operand 0 as label
  • %L0 - gives "l"
  • %n0 - negate operand 0 without $ prefix
  • %O0 - nothing
  • %P0 - same as %c0
  • %q0 - 64bit form of register operand 0 (rax)
  • %Q0 - gives "l"
  • %s0 - operand 0 with a comma appended
  • %S0 - gives "s"
  • %t0 - only usable on immediate operands, does nothing?
  • %T0 - gives "t"
  • %w0 - 16 bit form of register operand 0 (ax)
  • %W0 - gives "w"
  • %x0 - same as %w0
  • %y0 - same as %k0
  • %z0 - Opcode suffix based on operand 0 size (b, w, l), example asm ("mov%z1 %1, %0" : "=r"(ret) : "r"(val));

No comments: