Встроенная сборка GCC: перейти к маркировке внешнего блока

При использовании встроенного ассемблера в MSVC можно выйти за пределы ассемблерного блока, сославшись на метку в коде C/C++, как объяснено в этой статье MSDN.

Можно ли такое сделать при использовании встроенной сборки в GCC?

Вот пример того, что я пытаюсь выполнить:

__asm__ __volatile__ (
"   /* assembly code */ "
"   jz external_label;  "
);

/* some C code */

external_label:
/* C code coninues... */

Однако компилятор жалуется на то, что «external_label» не определен.


person Vicent Marti    schedule 13.04.2009    source источник


Ответы (2)


Код в этом ответе работает, но имеет неопределенное поведение и, как правило, нарушает работу при включенной оптимизации. Выйти из встроенного ассемблерного оператора безопасно только с помощью asm goto или под ограниченные обстоятельства, когда за оператором asm следует __builtin_unreachable();

(Здесь это неприменимо: никогда не бывает безопасно прыгать в середину встроенного ассемблерного оператора, а затем снова выпадать в сгенерированный компилятором код внутри функции.)


Что, если вы определите метку с помощью ассемблера?

asm("external_label:");

Обновление: этот код работает:

#include <stdio.h>

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

  return 0;
}
person Bastien Léonard    schedule 13.04.2009
comment
Я обновил образец, который кажется правильным. Работает ли это для вас? - person Bastien Léonard; 13.04.2009
comment
Хм... Это странно. Ваш код компилируется, однако, когда я делаю то же самое в моем, компоновщик все еще жалуется на неопределенную ссылку. :/ - person Vicent Marti; 13.04.2009
comment
На самом деле, я только что исправил. Оказывается, у вас не может быть ключевого слова «продолжить» между двумя переходами сборки, иначе все пойдет не так. :) Спасибо! - person Vicent Marti; 13.04.2009
comment
Кстати о метках, переходы с одного asm на другой не поддерживаются. Оптимизаторы компилятора не знают об этих скачках и поэтому не могут их учитывать при принятии решения о том, как оптимизировать. См. «Расширенный ассемблер с goto». См. gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html. - person jww; 17.06.2011
comment
кажется, этот код работает: Например: имеет неопределенное поведение? - person curiousguy; 30.10.2011
comment
@curiousguy: почему бы не прочитать комментарии? Особенно, если вы публикуете через два года после того, как я написал ответ... - person Bastien Léonard; 30.10.2011
comment
@BastienLéonard почему бы не прочитать комментарии? Вы имеете в виду, что очень маленький текст, объясняющий код, не работает? Особенно, если вы публикуете сообщение через два года после того, как я написал ответ... Я только что обнаружил эту страницу. Я предполагаю, что другие тоже найдут это. - person curiousguy; 31.10.2011

Начиная с GCC 4.5, вы также можете использовать asm goto. В следующем примере выполняется переход к метке C:

#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;
}
person chue x    schedule 03.07.2017