Labels in GCC inline assembly

39,064

Solution 1

A declaration of a local label is indeed a number followed by a colon. But a reference to a local label needs a suffix of f or b, depending on whether you want to look forwards or backwards - i.e. 1f refers to the next 1: label in the forwards direction.

So declaring the label as 1: is correct; but to reference it, you need to say jmp 1f (because you are jumping forwards in this case).

Solution 2

Well, this question isn't getting any younger, but there are two other interesting solutions.

1) This example uses %=. %= in an assembler template is replaced with a number that is "unique to each insn in the entire compilation. This is useful for making local labels that are referred to more than once in a given insn." Note that to use %=, you (apparently) must have at least one input (although you probably don't have to actually use it).

int a = 3;
asm (
    "test %0\n\t"
    "jnz to_here%=\n\t"
    "jz to_there%=\n\t"
    "to_here%=:\n\t"
    "to_there%=:"
    ::"r" (a));

This outputs:

test %eax
jnz to_here14
jz to_there14
to_here14:
to_there14:

Alternately, you can use the asm goto (Added in v4.5 I think). This actually lets you jump to c labels instead of just asm labels:

asm goto ("jmp %l0\n"
 : /* no output */
 : /* no input */
 : /* no clobber */
 : gofurther);

printf("Didn't jump\n");

// c label:
gofurther:
printf("Jumped\n");
Share:
39,064

Related videos on Youtube

Channel72
Author by

Channel72

Updated on December 29, 2020

Comments

  • Channel72
    Channel72 over 3 years

    In my ongoing experimentation with GCC inline assembly, I've run into a new problem regarding labels and inlined code.

    Consider the following simple jump:

    __asm__
    (
        "jmp out;"
        "out:;"
        :
        :
    );
    

    This does nothing except jump to the out label. As is, this code compiles fine. But if you place it inside a function, and then compile with optimization flags, the compiler complains: "Error: symbol 'out' is already defined".

    What seems to be happening is that the compiler is repeating this assembly code every time it inlines the function. This causes the label out to get duplicated, leading to multiple out labels.

    So, how do I work around this? Is it really not possible to use labels in inline assembly? This tutorial on GCC inline assembly mentions that:

    Thus, you can make put your assembly into CPP macros, and inline C functions, so anyone can use it in as any C function/macro. Inline functions resemble macros very much, but are sometimes cleaner to use. Beware that in all those cases, code will be duplicated, so only local labels (of 1: style) should be defined in that asm code.

    I tried to find more information about these "local labels", but can't seem to find anything relating to inline assembly. It looks like the tutorial is saying that a local label is a number followed by a colon, (like 1:), so I tried using a label like that. Interestingly, the code compiled, but at run time it simply triggered a Segmentation Fault. Hmm...

    So any suggestions, hints, answers...?

  • zwol
    zwol over 10 years
    @MichaelGraczyk Local labels are not an x86-specific feature. GAS supports them regardless of CPU or object file format, and so do nearly all other Unixy assemblers (as in, I've never seen one that didn't, even in 1995).
  • greggo
    greggo over 7 years
    Indeed and jmp 1 would be considered a jump to location 1, thus the segfault.
  • Omar Darwish
    Omar Darwish almost 2 years
    Where is this "%=" trick documented?
  • Omar Darwish
    Omar Darwish almost 2 years
    Found it. Documentation can be found in section "6.47.2.2 Assembler Template" here: gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
  • David Wohlferd
    David Wohlferd almost 2 years
    I'd probably link to this instead.