Арифметика адресов

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

Данные в секции .data идут непрерывно, поэтому мы можем перемещаться между отдельными кусочками данных применяя сложение или вычитание определенного количества байтов к адресам с помощью стандартных инструкций ADD и SUB. Особенно это удобно, когда нам надо перемещаться по элементам наборов данных. Например:

.global _start

_start:
    LDR X1, =nums    // помещаем в регистр X1 адрес метки nums - адрес указывает на число 11
    ADD X1, X1, 2 * 8   // прибавляем к адресу в регистре X1 2 * 8 = 16 байт  - адрес указывает на число 13

// завершение программы
    LDR X0, [X1]         // помещаем в регистр X0  число по адресу X1, то есть число 13
    MOV X8, #93         // номер функции Linux для выхода из программы - 93
    SVC 0               // вызываем функцию и выходим из программы

.data
    nums: .quad 11, 12, 13, 14

Здесь в регистр X1 загружается адрес метки nums, которая представляет набор из 4 чисел размером по 8 байт. Первое число равно 11, соответственно в X1 будет адрес числа 11:

LDR X1, =nums

Перейдем к 3-му числу в этом массиве:

ADD X1, X1, 2 * 8

Для большей показательности я использовал выражение 2 * 8, а не напрямую написал 16. То есть каждое число расположено от другого на расстоянии 8 байт (размер числа). Соответственно 3-е число расположено от 1-го числа на расстоянии 2 * 8 = 16 байт. Поэтому для получения адреса 3-го числа к адресу 1-го числа прибавляем 16 байт. Соответственно далее при загрузке данных по этому адресу в регистр X0 в нем окажется число 13

LDR X0, [X1]    // помещаем в регистр X0  число по адресу X1, то есть число 13

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

.global _start

_start:
    LDR X1, =nums    // помещаем в регистр X1 адрес метки nums - адрес указывает на число 11
    ADD X1, X1, 32   // прибавляем к адресу в регистре X1 32 байта  - адрес указывает на число myword

// завершение программы
    LDR X0, [X1]         // помещаем в регистр X0  число по адресу X1, то есть число 22
    MOV X8, #93         // номер функции Linux для выхода из программы - 93
    SVC 0               // вызываем функцию и выходим из программы

.data
    nums: .quad 11, 12, 13, 14
    myword: .word 22

То есть к адресу nums прибавляем 32 байта (4 числа по 8 байт) и таким образом получим адрес метки, которая идет после массива nums - метки myword.

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

.global _start

_start:
    LDR X1, =myword    // помещаем в регистр X1 адрес метки myword
    SUB X1, X1, #8   // вычитаем от адреса в регистре X1 8 байт - переходим к последнему числу в массиве nums

// завершение программы
    LDR X0, [X1]         // X0 = 14
    MOV X8, #93         // номер функции Linux для выхода из программы - 93
    SVC 0               // вызываем функцию и выходим из программы

.data
    nums: .quad 11, 12, 13, 14
    myword: .word 22

Здесь сначала вычитаем из загруженного адреса метки myword 8 байта и тем самым переходим к последнему числ из массива nums - числу 14.

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