12

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Vicent Marti
  • 7,203
  • 6
  • 30
  • 34

2 Answers2

11

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;
}
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Bastien Léonard
  • 60,478
  • 20
  • 78
  • 95
  • I updated with a sample that seems correct. Does it work for you? – Bastien Léonard Apr 13 '09 at 14:48
  • 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 Apr 13 '09 at 14:53
  • 1
    Actually, I've just fixed. Turns out you cannot have a 'continue' keyword between the two assembly jumps, or things go messy. :) Thanks! – Vicent Marti Apr 13 '09 at 14:57
  • 6
    "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 http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html. – jww Jun 16 '11 at 22:14
  • 3
    "_this code seems to work:_" As in: "has undefined behaviour"? – curiousguy Oct 30 '11 at 07:34
  • @curiousguy: why not read the comments? Especially if you're posting two years after I wrote the answer... – Bastien Léonard Oct 30 '11 at 09:45
  • 2
    @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. – curiousguy Oct 30 '11 at 23:42
6

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;
}
chue x
  • 18,573
  • 7
  • 56
  • 70