Объявление asm
Объявление asm даёт возможность встраивать исходный код на языке ассемблера в программу на C++. Это объявление поддерживается условно и определено реализацией, это означает, что оно может отсутствовать и, даже если оно предоставляется реализацией, может не иметь фиксированного значения.
Синтаксис
атрибуты (необязательно) asm ( сбалансированная-последовательность-токенов ) ;
|
|||||||||
| атрибуты | — | (начиная с C++11) любое количество атрибутов |
| сбалансированная-последовательность-токенов | — | последовательность токенов, в которой круглые, квадратные и фигурные скобки сбалансированы; любые ограничения на сбалансированную-последовательность-токенов и её значение определяются реализацией |
Объяснение
строковый-литерал обычно представляет собой короткую программу, написанную на языке ассемблера, которая выполняется всякий раз, когда выполняется это объявление. Различные компиляторы C++ имеют совершенно разные правила для asm-объявлений и разные соглашения для взаимодействия с окружающим кодом C++.
Как и другие объявления блоков, это объявление может появляться внутри блока (тела функции или другого составного оператора), и, как и все другие объявления, это объявление может также появляться вне блока.
| Этот раздел не завершён Причина: напишите заметку о расширенном синтаксисе ассемблера GCC, поскольку теперь он поддерживается Intel, IBM, Sun (начиная с v12) и т.д. |
Примечание
| Макрос Тестирования функциональности | Значение | Стандарт | Функциональность |
|---|---|---|---|
__cpp_constexpr |
201907L |
(C++20) | Тривиальная инициализация по умолчанию и объявление asm в constexpr функциях
|
Пример
Демонстрирует два вида встроенного синтаксиса ассемблера, предлагаемые компиляторами GCC/Clang. Эта программа будет корректно работать только на платформе x86_64 под Linux.
#include <iostream>
extern "C" int func(int x);
// определение func написано на ассемблере
// сырой строковый литерал может быть очень полезен
asm(R"(
.globl func
.type func, @function
func:
.cfi_startproc
movl %edi, %eax /* x находится в RDI, смотрите соглашение о вызовах x86-64 */
addl $1, %eax
ret
.cfi_endproc
)");
int main()
{
int n = func(0110);
// расширенный встроенный ассемблер
asm ("leal (%0,%0,4),%0"
: "=r" (n)
: "0" (n));
std::cout << "73*5 = " << n << std::endl; // намеренный сброс
// стандартный встроенный ассемблер
asm ("movq $60, %rax\n\t" // номер системного вызова exit в Linux
"movq $2, %rdi\n\t" // эта программа возвращает 2
"syscall");
}
Вывод:
73*5 = 365
Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
| Номер | Применён | Поведение в стандарте | Корректное поведение |
|---|---|---|---|
| CWG 195 | C++98 | требовалось поддерживать все объявления asm | сделано условно-поддерживаемым |
| CWG 2262 | C++11 | атрибуты не могут быть применены к asm объявлениям | позволено |
Смотрите также
Документация C по Встроенный ассемблер
|