Условные конструкции препроцессора

Последнее обновление: 21.01.2024

%if..%endif

Препроцессорная конструкция %if позволяет проверить значение некоторое условие - обычно значение препроцессорного символа и зависимости от результата проверки выполнить некоторые действия. Такая директива также обрабатывается препроцессором и заменяется на код ассемблера до собственно компиляции. Эта директива аналогичная конструкции if..else во ряде высокоуровневых языков программирования. В простейшем виде она имеет следующий синтаксис:

%if условие
действия, которые выполняются при истинности условия
%endif

Например:

global _start           

%define STATUS_CODE 22

section .text
_start:

%if STATUS_CODE == 22
    mov rdi, 44
%endif
    mov rax, 60
    syscall

Здесь проверяется значение константы STATUS_CODE. Если она равна 22, то в регистр rdi будет помещаться число 44. То есть в реальности к стадии компиляции мы получим текст программы:

global _start           

section .text
_start:
    mov rdi, 44
    mov rax, 60
    syscall

В качестве условия можно использовать стандартные операции сравнения:

  • Проверка на равенство - оператор ==

  • Проверка на неравенство - оператор !=

  • Другие операции сравнения (больше чем, меньше чем и т.д.) <, <=, >, >=

  • Логические операции, которые объединяют несколько операций сравнения - && (операция И - истинны должны быть оба условия), || (операция ИЛИ - истинным может быть хотя бы одно условие)

Пример:

        
%define STATUS_CODE 22

%if STATUS_CODE != 23 && STATUS_CODE > 10
    mov rdi, 41
%endif

Здесь условие истинно, если STATUS_CODE не равен 23 и больше 10.

Если нам надо добавить альтернативные действия на случай, если условие ложно, то применяется директива %else:

global _start           

%define STATUS_CODE 22

section .text
_start:

%if STATUS_CODE == 23
    mov rdi, 23       ; если STATUS_CODE равно 23, то в rdi число 23
%else
    mov rdi, 46       ; если STATUS_CODE не равно 23, то в rdi число 46
%endif
    mov rax, 60
    syscall

С помощью директивы %elif можно вводить альтернативные действия для дополнительных условий:

global _start           

%define STATUS_CODE 22

section .text
_start:

%if STATUS_CODE == 21
    mov rdi, 1
%elif STATUS_CODE == 22
    mov rdi, 2
%elif STATUS_CODE == 23
    mov rdi, 3
%else
    mov rdi, 4
%endif
    mov rax, 60
    syscall

Условная компиляция

NASM позволяет во время компиляции решать, будет ли та или иная часть файла участвовать в сборке приложения. Для этого применяется директива %ifdef. Она проверяет определение некоторого препроцессорного символа. Если символ определен, то в файл при компиляции добавляется код, который расположен между %ifdef и %endif. Например:

global _start           

%define SET_STATUS 1

section .data
%ifdef SET_STATUS
status_code: db 8
%endif

section .text
_start:

%ifdef SET_STATUS
    mov rdi, [status_code]
%endif
    mov rax, 60
    syscall

Здесь, если определен символ SET_STATUS, то в секции data определяется переменная status_code, а инструкция mov помещает ее значение в регистр rdi.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850