Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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"
);
like image 381
Sergey L. Avatar asked Nov 06 '12 15:11

Sergey L.


People also ask

What is __ asm __ in C?

The __asm keyword invokes the inline assembler and can appear wherever a C or C++ statement is legal. It cannot appear by itself. It must be followed by an assembly instruction, a group of instructions enclosed in braces, or, at the very least, an empty pair of braces.

What is inline assembly explain with an example?

In computer programming, an inline assembler is a feature of some compilers that allows low-level code written in assembly language to be embedded within a program, among code that otherwise has been compiled from a higher-level language such as C or Ada.

Is asm a keyword in C?

The asm keyword allows you to embed assembler instructions within C code. GCC provides two forms of inline asm statements. A basic asm statement is one with no operands (see Basic Asm), while an extended asm statement (see Extended Asm) includes one or more operands.


2 Answers

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.

like image 109
FrankH. Avatar answered Oct 20 '22 08:10

FrankH.


Your only option is to use Intel syntax. GCC, of course, can generate insn like mov off(base, index, scale), but does this on the level of whole MEM RTL expressions, i.e. not having offset, base, etc like individual operands.

So, Intel syntax, compile the following with gcc -c -masm=intel x.c:

#include <stddef.h>

struct s
{
  int a, b;
};

int foo (struct s *s, int i)
{
  int r;
  asm (
       "mov %[r], dword ptr [%[s]+%[index]*8 + %[displ]] "
       : [r] "=r" (r)
       : [s] "r" (s) , [index] "r" (i),
         [displ] "e" (offsetof(struct s, b))
       :
       );

  return r;
}
like image 2
chill Avatar answered Oct 20 '22 07:10

chill