Перейти к основному содержимому

Макросы и условная сборка

Разработчику

Контекст: NASM. Макросы обрабатывает ассемблер при сборке, процессор их не выполняет. См. Основы про различие мнемоник и директив.

Макрос и подпрограмма

Подпрограмма (call)Макрос (%macro)
Когда разворачиваетсяпри запускепри сборке
Размер кодаодин экземпляр в .textкопия на каждый вызов макроса
Стоимостьпереход + стектолько инструкции тела
Отладкаодна меткаповторяющиеся блоки в листинге

Макрос уместен для коротких шаблонов (пролог, обёртка над syscall, развёртка цикла). Длинную логику выносят в call.


Текстовые константы — %define

%define SYS_WRITE 1
%define SYS_EXIT 60
%define STDOUT 1

mov rax, SYS_WRITE
mov rdi, STDOUT

Препроцессор подставляет текст до разбора инструкций. Это не переменная в памяти и не символ линкера.


Параметризованный макрос — %macro

%macro exit 1
mov rax, 60
mov rdi, %1
syscall
%endmacro

_start:
; ...
exit 0
  • Имя: exit.
  • Число после имени: обязательное количество аргументов (1).
  • %1, %2 … — подстановка аргументов.

Макрос с необязательными параметрами: %macro name min [-max+].


Локальные метки в макросах

Если макрос содержит метки, при повторном включении имена столкнутся. В NASM используют %% для метки, уникальной на каждое раскрытие:

%macro push_callee_saved 0
push rbx
push rbp
push r12
push r13
push r14
push r15
%endmacro

%macro pop_callee_saved 0
pop r15
pop r14
pop r13
pop r12
pop rbp
pop rbx
%endmacro

Внутри макроса с циклом:

%macro rep_zero 2
xor rax, rax
%%loop:
mov [%1 + %2 * 8 - 8], rax ; пример: обнулить массив слов
dec %2
jnz %%loop
%endmacro

Условная сборка — %if, %ifdef

%define ARCH_BITS 64

%if ARCH_BITS == 64
%define PTR_SIZE 8
%else
%define PTR_SIZE 4
%endif

Проверка наличия макроса:

%ifdef DEBUG
; вставить отладочный вывод
%endif

Так собирают разные варианты одного файла без ручного редактирования (отладка, платформа, размер слова).


%include — подключение файла

%include "macros.inc"
%include "syscall.inc"

Содержимое включается как будто вставлено в текущую позицию. Удобно для общих макросов и констант; исполняемый код чаще выносят в отдельные .asm с global/extern — см. несколько модулей.


Типичные ошибки

ПроблемаРешение
Метка loop: в макросе, вызванном дважды%%loop
Ожидание, что %1 вычислится в runtimeаргументы макроса — константы сборки
Огромный макрос в горячем циклераздувает I-cache; заменить на call
%define с выражением с запятойиспользовать скобки или %assign для чисел

%assign counter 0 — целочисленная переменная времени сборки (можно %assign counter counter+1 в макросе для генерации таблиц).


Макрос для системного вызова (Linux x86-64)

%macro syscall3 3
mov rax, %1
mov rdi, %2
mov rsi, %3
syscall
%endmacro

; syscall3 1, 1, msg ; write — для полного write нужен ещё rdx

Для четырёх и более аргументов расширяют шаблон (rdx, r10 … по ABI). Полная таблица номеров — в справочнике.


См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).