◐ Shell
clean mode source ↗

Объявление asm — cppreference.com

Материал из cppreference.com

Объявление asm даёт возможность встраивать исходный код на языке ассемблера в программу на C++. Это объявление поддерживается условно и определено реализацией, это означает, что оно может отсутствовать и, даже если оно предоставляется реализацией, может не иметь фиксированного значения.

Синтаксис

атрибуты (необязательно) asm ( сбалансированная-последовательность-токенов ) ;
атрибуты (начиная с C++11) любое количество атрибутов
сбалансированная-последовательность-токенов последовательность токенов, в которой круглые, квадратные и фигурные скобки сбалансированы; любые ограничения на сбалансированную-последовательность-токенов и её значение определяются реализацией

Объяснение

строковый-литерал обычно представляет собой короткую программу, написанную на языке ассемблера, которая выполняется всякий раз, когда выполняется это объявление. Различные компиляторы C++ имеют совершенно разные правила для asm-объявлений и разные соглашения для взаимодействия с окружающим кодом C++.

Как и другие объявления блоков, это объявление может появляться внутри блока (тела функции или другого составного оператора), и, как и все другие объявления, это объявление может также появляться вне блока.

Примечание

Макрос Тестирования функциональности Значение Стандарт Функциональность
__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");
}

Вывод:

Отчёты о дефектах

Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:

Номер Применён Поведение в стандарте Корректное поведение
CWG 195 C++98 требовалось поддерживать все объявления asm сделано условно-поддерживаемым
CWG 2262 C++11 атрибуты не могут быть применены к asm объявлениям позволено

Смотрите также

Внешние ссылки

1.  HOWTO по Встроенному Ассемблеру GCC
2.  Встроенный Ассемблер IBM XL C/C++
3.  Встроенный Ассемблер Intel C++
4.  Встроенный Ассемблер Visual Studio 2013
5.  Операторы Ассемблера Sun Studio 12
6.  Встроенный ассемблер для HP-UX на базе Itanium
7.  Соглашения о вызовах X86 — Из Википедии