Определение данных в ассемблере armasm64

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

Синтаксис определения данных в ассемблере armasm64 на Windows несколько отличается от того, что применяется в ассемблере GAS GNU. Данные в armasm64 определяются с помощью одной из следующих директив:

  • DCB: выделяет память для одного и более чисел размером в 1 байт. В качестве значения принимает число от –128 до 255

  • DCD: выделяет память для одного и более слов (чисел размером в 4 байта), которые выровнены по 4 байтам. То есть если адрес слова по умолчанию не выровнен, то к перед ним дополнительно добавляются необходимые нулевые байты таким образом, чтобы адрес числа оказался выровненным по 4-байтовой границе. Директива DCDU также определяет 4-байтовое число, одно для него не выполняется выравнивание

  • DCW: выделяет память для одного и более полуслов (число размером в 2 байта), которые выровнены по 2 байтам. Директива DCWU также определяет 2-байтовое число, но без выравнивания

  • DCQ: выделяет память для одного и более двойных слов (число размером в 8 байт), которые выровнены по 4 байтам. Директива DCQU также определяет двойное слово, но без выравнивания

  • DCFD: выделяет память для одного и более чисел с плавающей точкой двойной точности (размером в 8 байт), которые выровнены по 4 байтам. Директива DCFDU также определяет число с плавающей точкой двойной точности, но без выравнивания

  • DCFS: выделяет память для одного и более чисел с плавающей точкой одинарной точности (размером в 4 байта), которые выровнены по 4 байтам. Директива DCFSU также определяет число с плавающей точкой одинарной точности, но без выравнивания

Например, определим несколько чисел:

    area main, CODE
    global __main

__main
    ldr x0, num1       ; загружаем в X0 значение переменной num1
    
    ret               
num1 dcq 11     ; 8-байтовое число (двойное слово)
num2 dcd 12     ; 4-байтовое число (слово)
num3 dcw 13     ; 2-байтовое число (полслова)
num4 dcb 14     ; 1 байт
    end

В данном случае в разделе кода после завершения функции __main определяются 4 числа разных типов. В самой функции с помощью директивы LDR в регистр Х0 загружается число num1.

Выравнивание

Если в примере выше мы попробуем загрузить в регистр однобайтовое число num4, то мы получим ошибку

ldr x0, num4  ; ! Ошибка

Поскольку перед числом num4 расположено 2-байтовое число num3, то num4 НЕ будет выровнено по 4-байтовой границе, и при компиляции мы получим ошибку о том, что должное выравнивание отсутствует. Для этого мы можем применить директиву ALIGN, которой передается количество байт, по которым надо выровнять данные:

    area main, CODE
    global __main

__main
    ldr x0, num4       ; загружаем в X0 значение переменной num4
    
    ret               
num1 dcq 11 
num2 dcd 12  
num3 dcw 13
    align 4    
num4 dcb 14     ; num4 выровнено по 4 байтам
    end

Определение массивов

Для определения массива данных все элементы перечисляются через запятую:

    area main, CODE
    global __main

__main
    ldr x0, nums    ; X0 = 11
    
    ret               
nums dcq 11, 12, 13, 14, 15, 16
    end

В данном случае определен массив nums, который состоит из шести 8-байтных чисел.

Для упрощения определения наборов данных можно применять директивы SPACE и FILL. Директива SPACE определеяет набор из определенного количества байтов, например:

data1 space 255         ; определяет 255, заполненных нулями

Здесь data1 представляет набор из 255 байтов, каждый из которых равен 0.

Директива FILL имеет следующий синтаксис:

FILL count, value, size

где count - количество чисел в наборе, value - значение, которым инициализируется каждое число, а size - размер каждого числа. Но тут есть ограничения. Во-первых, в качестве размера может выступать 1, 2 или 4 байта. А общее количество чисел в наборе должно быть кратно размеру. Например:

data2 fill 32, 7, 4

Здесь массив data2 определяет 32 числа размером по 4 байта, каждое из которых равно 7.

Определение строки

Строка символов ASCII по сути представляет набор байтов, и соответственно для определения строки применяется директива DCB. Строка заключается в кавычки:

    area main, CODE
    global __main

__main
    ldr x0, =message    ; в Х0 адрес строки message
    
    ret               
message dcb "Hello METANIT.COM"
    end

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

message dcb "Hello METANIT.COM"

Раздел DATA

По умолчанию, если данные располагаются внутри раздела CODE, то их нельзя изменить, фактически они выступают как константы. Если же надо, чтобы данные можно было изменять, они помещаются в раздел DATA, который определяется с помощью директивы AREA:

    area main, CODE     ; начало раздела CODE
    global __main

__main
    ldr x1, =message    ; загружаем в X1 адрес message
    mov w0, #'a'
    strb w0, [x1, #1]   ; изменяем второй байт строки на "a"

    ret 

    area DATA       ; начало раздела DATA          
message dcb "Hello METANIT.COM"
    end

Здесь изменяем значение второй байта строки message - с "e" на "a".

Определение констант

Еще один момент, который отличается от синтаксиса ассемблера GAS - это определение констант. В armasm64 константы также определяются с помощью директивы EQU, но в другой форме:

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

Например:

    area main, CODE     ; начало раздела CODE
    global __main

__main
    mov x0, len     ; X0 = len
    ret 

    area DATA       ; начало раздела DATA          
message dcb "Hello METANIT.COM"
len EQU 17      ; len = 17
    end

Здесь определяется константа len, которая равна 17. И с помощью инструкции mov значение этой константы помещаем в регистр.

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