GCC Inline Assembly: Jump to label outside block

13,739

Solution 1

The code in this answer happens to work, but is undefined behaviour and will in general break things with optimization enabled. It's only safe to jmp out of an inline asm statement with asm goto, or under limited circumstances when the asm statement is followed by __builtin_unreachable();

(That's not usable here: it's never safe to jump into the middle of an inline asm statement and then fall out into compiler-generated code again inside a function.)


What if you define the label with the assembler?

asm("external_label:");

Update: this code seems to work:

#include <stdio.h>

int
main(void)
{
  asm("jmp label");
  puts("You should not see this.");
  asm("label:");

  return 0;
}

Solution 2

As of GCC 4.5, you can also use asm goto. The following example jumps to a C label:

#include <stdio.h>

int main(void) {
    asm goto (
        "jmp %l[done]"  // %l == lowercase L
        :
        :
        :
        : done          // specify c label(s) here
    );
    printf("Should not see this\n");

done:
    printf("Exiting\n");
    return 0;
}
Share:
13,739
Vicent Marti
Author by

Vicent Marti

Updated on June 05, 2022

Comments

  • Vicent Marti
    Vicent Marti almost 2 years

    When using inline assembly under MSVC, one is allowed to jump outside of the assembly block by referencing a label in the C/C++ code, as explained in this MSDN article.

    Can such thing be done when using inline assembly under GCC?

    Here's an example of what I'm trying to accomplish:

    __asm__ __volatile__ (
    "   /* assembly code */ "
    "   jz external_label;  "
    );
    
    /* some C code */
    
    external_label:
    /* C code coninues... */
    

    The compiler, however, complains about "external_label" not being defined.

  • Bastien Léonard
    Bastien Léonard about 15 years
    I updated with a sample that seems correct. Does it work for you?
  • Vicent Marti
    Vicent Marti about 15 years
    Hmm... This is strange. Your code does compile, however when doing the same thing in mine, the linker still complains about an undefined reference. :/
  • Vicent Marti
    Vicent Marti about 15 years
    Actually, I've just fixed. Turns out you cannot have a 'continue' keyword between the two assembly jumps, or things go messy. :) Thanks!
  • jww
    jww almost 13 years
    "Speaking of labels, jumps from one asm to another are not supported. The compiler's optimizers do not know about these jumps, and therefore they cannot take account of them when deciding how to optimize. See 'Extended asm with goto'." See gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html.
  • curiousguy
    curiousguy over 12 years
    "this code seems to work:" As in: "has undefined behaviour"?
  • Bastien Léonard
    Bastien Léonard over 12 years
    @curiousguy: why not read the comments? Especially if you're posting two years after I wrote the answer...
  • curiousguy
    curiousguy over 12 years
    @BastienLéonard "why not read the comments?" You mean the very small text that explains the code doesn't work? "Especially if you're posting two years after I wrote the answer..." I have just discovered this page. I assume others will find it too.