Данные в секции .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.