Константы

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

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

Директива .EQU

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

.EQU название, значение

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

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

.globl _start
.equ var1, 1
.equ var2, 2
.equ var3, 3

.text
_start:
    movq $var1, %rdi    # RDI = 1
    addq $var2, %rdi    # RDI = RDI + 2 = 3
    addq $var3, %rdi    # RDI = RDI + 3 = 6
    movq $60, %rax
    syscall

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

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

.globl _start
.equ var1, 1
.equ var2, 2
.equ var3, 3

.text
_start:
    movq $1, %rdi    # RDI = 1
    addq $2, %rdi    # RDI = RDI + 2 = 3
    addq $3, %rdi    # RDI = RDI + 3 = 6
    movq $60, %rax
    syscall

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

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

.globl _start
.equ first, 0 
.equ second, first + 8
.equ third, second + 8

.data
nums: .quad 5, 6, 7

.text
_start:
    movq $third, %rdi    # RDI = 16

    movq $60, %rax
    syscall

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

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

.globl _start
.equ first, 0 
.equ second, first + 8
.equ third, second + 8

.data
nums: .quad 5, 6, 7

.text
_start:
    movq $nums, %rbx        # в RBX адрес переменной nums
    movq third(%rbx), %rdi  # в RDI значение по адресу (RBX + third)

    movq $60, %rax
    syscall

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

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

.globl _start

.equ intSize, 4

.data
num1: .quad intSize
num2: .quad intSize + 4

.text
_start:
    movq num1, %rdi  # RDI=4

    movq $60, %rax
    syscall

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

Определение констант без директивы .equ

Второй - упрощенный способ определения констант заключается в присваивании некоторому идентификатору какого-нибудь значения:

.globl _start

intSize=4

.data
num1: .quad intSize
num2: .quad intSize + 4

.text
_start:
    movq num1, %rdi  # RDI=4

    movq $60, %rax
    syscall

Таким образом, следующие два способа определения констант будут аналогичны:

intSize = 4
.equ intSize, 4
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850