Ассемблер позволяет определять указатели - переменные, которые хранят адрес других объектов. Для получения адреса объекта применяется выражение
offset переменная
Поскольку адрес в архитектуре x86-64 занимает 8 байт, то для хранения адреса нам надо определить переменную с типом qword. Например, определим переменную и получим ее адрес:
.data n dword 22 pn qword ? .code main proc ; установка указателя mov rax, offset n ; загружаем адрес переменной n mov pn, rax ; сохраняем адрес в переменную pn ; получение данных по указателю mov rbx, pn ; в rbx помещаем адрес из переменной pn mov rax, [rbx] ; обращаемся по адресу из rbx ret main endp end
Здесь определена переменная-указатель pn, которая представляет тип qword и которая будет хранить адрес переменной n. Сначала получаем адрес в регистр RAX и затем передаем его в указатель pn:
mov rax, offset n mov pn, rax
Если нам надо использовать значение по указателю, можно сначала поместить значение указателя в регистр, а затем использовать косвенную адресацию для получения самого значения по указателю.
mov rbx, pn ; в rbx помещаем адрес из переменной p mov rax, [rbx] ; обращаемся по адресу из rbx
В итоге в регистре RAX окажется число 22 - значение переменной n.
При этом мы можем получить адрес уже при определении переменной-указателя:
.data n dword 11 pn qword offset n ; получаем адрес переменной n .code main proc ; получение данных по указателю mov rbx, pn ; в rbx помещаем адрес из переменной pn mov rax, [rbx] ; в RAX число 11 ret main endp end
Указатель необязательно должен представлять переменную - это может быть и константа:
pn equ offset n ; константа pn указывает на переменную n .data n dword 12 .code main proc ; получение данных по указателю mov rbx, pn ; в rbx помещаем адрес из переменной pn mov rax, [rbx] ; в RAX число 11 ret main endp end
При получении адреса мы можем использовать ряд операций:
offset переменная [смещение] offset переменная + смещение offset переменная - смещение
В этом случае мы можем получить адрес, который смещен относительно адреса переменной на несколько байтов вперед или назад. Выражение переменная [смещение]
фактически эквивалентно выражению переменная + смещение
. Например:
.data nums dword 11, 12, 13, 14, 15, 16 p qword ? .code main proc ; установка указателя mov rax, offset nums + 4 ; загружаем адрес переменной nums + 4 mov p, rax ; сохраняем адрес в переменную p ; получение данных по указателю mov rbx, p ; в rbx помещаем адрес из переменной p mov rax, [rbx] ; обращаемся по адресу из rbx ret main endp end
Здесь переменная nums представляет набор 32-битных чисел. Выражение offset nums
возвращает адрес перемнной num - адрес первого числа из этого набора. Соответственно
чтобы получить адрес второго числа из этого набора, нам надо прибавить размер одного элемента в байтах, то есть 4 байта - offset nums + 4