Передача в функцию адресов

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

В прошлых темах черехз регистры в функции передавались параметры, которые представляли непосредственнр сами значения, то есть это была так называемая передача параметров по значению. Но также можно передавать адреса этих значений. Получив в функции адрес, необходимо сначала обратиться по этому адресу, чтобы получить хранящееся по этому адресу значение. А потом собственно и производить все необходимые операции с полученным значением. Рассмотрим, как в функцию можно передать адрес на примере функции обмена значениями:

.equ a, 0
.equ b, 8

.global _start 
_start: 
    sub sp, sp, #16      // выделяем в стеке 16 байт для двух 8-байтных локальных переменных 
    mov x0, 5
    str x0, [sp, a]     // сохраняем первую переменную - a (a= 5)
    mov x0, 101
    str x0, [sp, b]     // сохраняем вторую переменную - b (b= 101)

    add x0, sp, a       // в Х0 адрес первой локальной переменной - переменной a
    add x1, sp, b       // в Х1 адрес второй локальной переменной - переменной b

    bl swap             // вызываем функцию swap для обмена значениями

    ldr x0, [sp, b]     // проверяем значение переменной b
    add sp, sp, #16     // восстанавливаем стек
    mov x8, #93       // устанавливаем функцию Linux для выхода из программы
    svc 0             // Вызываем функцию Linux

swap:
    ldr x2, [x0]    // загружаем данные по адресу из X0 в X2
    ldr x3, [x1]    // загружаем данные по адресу из Х1 в Х3
    str x2, [x1]    // сохраняем данные из Х0 по адресу в Х1
    str x3, [x0]    // сохраняем данные из X1 по адресу в Х0
    ret

Здесь в стек загружаются два значения - две локальных переменных, которые условно назовем a и b. Для переменной a в стеке применяется смещение 0, а для переменной b - смещение в 8 байт.

mov x0, 5
str x0, [sp, a]     // сохраняем первую переменную - a (a= 5)
mov x0, 101
str x0, [sp, b]     // сохраняем вторую переменную - b (b= 101)

Для большей наглядности вместо конкретных смещений применяются константы a и b, которые при компиляции заменяются на 0 и 8 соответственно.

Затем в регистры X0 и X1 помещаем параметры для функции swap:

add x0, sp, a       // в Х0 адрес первой локальной переменной - переменной a
add x1, sp, b       // в Х1 адрес второй локальной переменной - переменной b

В итоге в регистре X0 будет значение SP+a=SP+0=SP, то есть тот адрес, который хранится в SP и по которому располагается переменная a. А в регистр Х1 помещаем адрес SP+b=SP+8, то есть смещение относительно значения SP на 8 байт - тот адрес, по которому располагается переменная b. Таким образом, регистры Х0 и Х1 хранят не сами значения, а адреса этих значений.

Далее вызываем функцию swap:

bl swap // вызываем функцию swap для обмена значениями

В функции swap загружаем собственно значения по переданным адресам в регистры Х2 и Х3:

ldr x2, [x0]    // загружаем данные по адресу из X0 в X2
ldr x3, [x1]    // загружаем данные по адресу из Х1 в Х3

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

Затем загруженные данные сохраняются по противоположным адресам:

str x2, [x1]    // сохраняем данные из Х0 по адресу в Х1
str x3, [x0]    // сохраняем данные из X1 по адресу в Х0

То есть регистр Х2 хранит значение из адреса в Х0 и сохраняется в адрес из регистра Х1. А регистр Х3 хранит значение по адресу из Х1 и сохраняет это значение в адрес из регистра Х0. Таким образом произойдет обмен значениями.

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