Spec-Zone.ru › GCC 15

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

Оператор asm имеет следующий синтаксис:

asm asm-qualifiers ( AssemblerInstructions )

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

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

volatile

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

inline

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

Параметры

AssemblerInstructions

Это строковый литерал, задающий ассемблерный код. В C++ с -std=gnu++11 или более поздним стандартом он также может быть константным выражением в скобках (см. раздел Константные выражения C++11 вместо строковых литералов).

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

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

Замечания

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

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

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

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

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

При определенных обстоятельствах GCC может дублировать ваш ассемблерный код (или удалять его дубликаты) при оптимизации. Если в ассемблерном коде определяются символы или метки, это может привести к неожиданным ошибкам компиляции из-за дублирования символов.

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

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

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

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

На целевых платформах, таких как 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-15.3.0/gcc/Basic-Asm.html

Spec-Zone.ru

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