Константы

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

В отличие от переменных константы представляют неизменяемые значения. Ассемблер NASM позволяет определять константы двумя способами.

Директива EQU

Директива EQU позволяет определить константы, которые будут заменяться ассемблером на из значения при компиляции программы. Синтаксис данной инструкции:

название_константы equ значение_константы

В качестве названия константы используется набор символов, обычно некоторое описательное название, которое указывает на предназначение данной константы.

В качестве значения используется некоторое число или выражение, которое возвращает число. Например:

global _start

const1 equ 1
const2 equ 2
const3 equ 3

section .text
_start:
    mov rdi, const1    ; RDI = 1
    add rdi, const2    ; RDI = RDI + 2 = 3
    add rdi, const3    ; RDI = RDI + 3 = 6
    mov rax, 60
    syscall 

В данном случае с помощью директивы equ определяются три контанты: const1, const2, const3. Каждой из них сопоставляется числовое значение 1, 2, 3.

Далее мы можем использовать эти константы как стандартные числа, и ассемблер при компиляции заменит эти константы на их значения. То есть предыдущий код фактически эквивалентен следующему:

global _start

section .text
_start:
    mov rdi, 1    ; RDI = 1
    add rdi, 2    ; RDI = RDI + 2 = 3
    add rdi, 3    ; RDI = RDI + 3 = 6
    mov rax, 60
    syscall 

Но использование описательных имен вместо их значений в тексте программы позволяет легче ориентироваться в коде программы, быстрее понять предназначение тех или иных значений.

Стоит отметить, что после названия константы при ее определении может идти двоеточие, которое необязательно:

const1: equ 1

Константы могут динамически вычисляться

global _start

first equ 0 
second equ first + 8    ; second = 8
third equ second + 8    ; third = 16

section .text
_start:
    mov rdi, first    ; RDI = 0
    add rdi, second    ; RDI = RDI + 8 = 8
    add rdi, third    ; RDI = RDI + 16 = 24
    mov rax, 60
    syscall 

Выражения, которые возвращают значение констант, могут применять стандартные арифметические операции, как сложение, вычитание, умножение, где операндами могут быть в том числе и другие константы. Так, в данном случае определяются три константы, которые определяют смещение элементов в массиве nums. Значение константы second зависит от константы first, значение third - от значения константы second. Но в любом случае значения этих констант вычисляется на этапе компиляции.

Соответственно мы можем использовать константы в том числе и в качестве смещения для вычисления адреса. Например, получим значение третьего элемента массива из 8-байтовых чисел в программе на Linux:

global _start

section .data
nums dq 5, 6, 7

first equ 0 
second equ first + 8    ; second = 8
third equ second + 8    ; third = 16

section .text
_start:
    mov rdi, [nums + third]    ; RDI = 7
    mov rax, 60
    syscall 

Вместо константы third мы могли бы использовать конкретное число - 16, но third как описательное имя позволит лучше описать намерение, которое заложено в программу.

Аналогичный пример на Windows:

global _start

section .data
nums dq 5, 6, 7

first equ 0 
second equ first + 8    ; second = 8
third equ second + 8    ; third = 16

section .text
_start:
    mov rax, qword [rel nums + third]    ; RDI = 7
    ret    

Также константы могут применяться для определения значений переменных. Пример программы для Linux:

global _start

section .data
num1 dq intSize         ; num1 = 4
num2 dq intSize + 4     ; num2 = 4 + 4 = 8

intSize equ 4

section .text
_start:
    mov rdi, [num2]    ; RDI = 8
    mov rax, 60
    syscall 

В данном случае переменные num1 и num2 получают соответственно значения константы intSize и результат выражения (intSize+4).

Аналогичный пример для Windows:

global _start

section .data
num1 dq intSize         ; num1 = 4
num2 dq intSize + 4     ; num2 = 4 + 4 = 8

intSize equ 4

section .text
_start:
    mov rax, qword [rel num2]    ; RAX = 7
    ret    

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