Объявление 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 по Встроенный ассемблер
|