Search code examples
cgccinline-assemblyi386

GCC extended asm, struct element offset encoding


I am trying to write a small piece of my code in GCC style extended asm (x86-64 target) and am having trouble encoding struct offsets.

I have a struct s with a member size_t a[], a pointer to such a struct and an index both of which are generated within the asm block.

Now I need to address that element in asm

asm (
    "mov %[displ](%[s], %[index], 8), %%rbx"
    : [s] "+r" (s)
    , [index] "+r" (i)
    : "memory", "cc", "rax", "rbx"
);

How can I encode displ into the asm block? Passing offsetof(struct s, a) as an immediate prefixes it with $ and generates invalid assembly.

asm (
    "mov %[displ](%[s], %[index], 8), %%rbx"
    : [s] "+r" (s)
    , [index] "+r" (i)
    : [displ] "i" (offsetof(struct s, a))
    : "memory", "cc", "rax", "rbx"
);

Solution

  • It actually is possible, using the %c... operand modifier:

    #include <stddef.h>
    #include <stdint.h>
    
    struct s
    {
      int a, b;
    };
    
    int foo (struct s *s, int i)
    {
      int r;
      asm (
           "movl %c[displ](%[s],%[index],8), %[r]\n\t"
           : [r] "=r" (r)
           : [s] "r" (s) , [index] "r" ((uintptr_t)i),
             [displ] "e" (offsetof(struct s, b))
           :
           );
    
      return r;
    }

    Thanks where thanks is due - found that here. There's a gcc mailing list posting referring to this as well; the keywords there are "output substitution".
    The stackoverflow posting What does %c mean in GCC inline assembly code? also has an explanation about %c in particular.