Spec-Zone.ru › GCC 13

6.47.1 Базовые ассемблерные инструкции без операндов

Базовое asm выражение имеет следующий синтаксис:

asm asm-qualifiers ( AssemblerInstructions )

Для языка C ключевое слово asm является расширением GNU. При написании кода C, который может быть скомпилирован с опциями -ansi и -std, выбирающими диалекты C без расширений GNU, используйте __asm__ вместо asm (см. Альтернативные ключевые слова). Для языка C++ asm — стандартное ключевое слово, но __asm__ можно использовать для кода, скомпилированного с -fno-asm.

Квалификаторы

volatile

Необязательный квалификатор volatile не оказывает никакого влияния. Все базовые asm блоки неявно являются переменными.

inline

Если вы используете квалификатор inline, то для целей встраивания размер asm выражения принимается как наименьший возможный (см. Размер asm).

Параметры

AssemblerInstructions

Это строка, которая задаёт ассемблерный код. Строка может содержать любые инструкции, распознаваемые ассемблером, включая директивы. GCC не анализирует сами ассемблерные инструкции и не знает, что они означают или даже являются ли они корректным ассемблерным вводом.

Вы можете поместить несколько ассемблерных инструкций вместе в одну asm строку, разделяя их символами, обычно используемыми в ассемблерном коде для системы. Комбинация, работающая в большинстве случаев, — это перевод строки и табуляция (записанная как ‘\n\t’). Некоторые ассемблеры позволяют использовать точки с запятой в качестве разделителя строк. Однако обратите внимание, что некоторые диалекты ассемблера используют точки с запятой для начала комментария.

Замечания

Использование расширенных asm (см. Расширенный ассемблерный код с операндами выражений C) обычно приводит к более компактному, безопасному и эффективному коду, и в большинстве случаев это лучшее решение, чем базовый asm. Однако есть две ситуации, где можно использовать только базовый asm:

  • Расширенные asm выражения должны находиться внутри функции C, поэтому для записи встроенного ассемблерного языка на уровне файла («глобально»), вне функций C, необходимо использовать базовый asm. Вы можете использовать этот метод для вывода директив ассемблера, определения макросов ассемблерного языка, которые можно вызывать в других частях файла, или записи целых функций на ассемблерном языке. В базовых asm выражениях вне функций нельзя использовать квалификаторы.
  • Функции, объявленные с атрибутом naked, также требуют базового asm (см. Объявление атрибутов функций).

Безопасный доступ к данным C и вызов функций из базового asm сложнее, чем может показаться. Для доступа к данным C лучше использовать расширенный asm.

Не ожидайте, что последовательность asm выражений останется идеально последовательной после компиляции. Если определённые инструкции должны оставаться последовательными в выходе, поместите их в одно asm выражение с несколькими инструкциями. Обратите внимание, что оптимизаторы GCC могут перемещать asm выражения относительно других участков кода, включая переходы.

asm выражения не могут выполнять переходы в другие asm выражения. GCC не знает об этих переходах и, следовательно, не может учитывать их при принятии решения об оптимизации. Переходы из asm к меткам C поддерживаются только в расширенных asm.

В некоторых случаях GCC может дублировать (или удалять дубликаты) вашего ассемблерного кода при оптимизации. Это может привести к неожиданным ошибкам дублирования символов во время компиляции, если ваш ассемблерный код определяет символы или метки.

Предупреждение: Стандарты C не определяют семантику asm, что делает её потенциальным источником несовместимости между компиляторами. Эти несовместимости могут не порождать предупреждения/ошибки компилятора.

GCC не анализирует базовые asm выражения AssemblerInstructions, что означает, что нет способа сообщить компилятору, что происходит внутри них. GCC не имеет доступа к символам в asm и может отбросить их как неиспользуемые. Он также не знает о побочных эффектах ассемблерного кода, таких как изменения в памяти или регистрах. В отличие от некоторых компиляторов, GCC предполагает, что изменения в общих регистрах не происходят. Это предположение может измениться в будущей версии.

Чтобы избежать проблем, связанных с будущими изменениями семантики и проблемами совместимости между компиляторами, рассмотрите возможность замены базового asm расширенным asm. См. Как преобразовать базовый ассемблерный код в расширенный для получения информации о выполнении этого преобразования.

Компилятор копирует ассемблерные инструкции в базовом asm дословно в файл выходного ассемблерного кода, не обрабатывая диалекты или какие-либо операторы ‘%’, которые доступны в расширенных asm шаблонах. Это приводит к небольшим различиям между базовыми asm строками и расширенными asm шаблонами. Например, для ссылки на регистры можно использовать ‘%eax’ в базовом asm и ‘%%eax’ в расширенном asm.

На целевых платформах, таких как x86, поддерживающих несколько диалектов ассемблера, все базовые asm блоки используют диалект ассемблера, заданный опцией командной строки -masm (см. Опции x86). Базовые asm не предоставляют механизма для предоставления разных ассемблерных строк для разных диалектов.

Для базового asm с непустой строкой ассемблерного кода GCC предполагает, что ассемблерный блок не изменяет общие регистры, но может считывать или записывать любые глобально доступные переменные.

Вот пример базового asm для i386:

/* Note that this code will not compile with -masm=intel */
#define DebugBreak() asm("int $3")

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-13.3.0/gcc/Basic-Asm.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API