Указатель на процедуру

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

Архитектура x86-64 допускает три основные формы вызова процедуры: через имя процедуры, путем косвенной адресации через 64-битный регистр общего назначения и через переменную-указатель

call имя_процедуры  ; прямой вызов
call регистр        ; косвенный вызов через регистр
call указатель      ; косвенный вызов через указатель-адрес процедуры

При вызове процедуры через регистр процессор x86-64 сначала помещает адрес возврата в стек, а затем начинает выборку следующего байта кода операции (инструкции) с адреса, указанного значением в регистре. При этом регистр должен быть 64-разрядным. Третья форма инструкции call извлекает адрес первой инструкции процедуры из переменной-указателя. Вычислить адрес процедуры можно либо с помощью оператора offset, либо с помощью инструкции lea.

Пример вызова через регистр:

.code
sum proc
    mov rax, rcx
    add rax, rdx
    ret
sum endp

main proc
    mov rcx, 22
    mov rdx, 24
    mov rax, offset sum     ; в RAX помещаем адрес процедуры sum
    call rax    ; вызываем процедуру sum
    ret
main endp
end

Здесь с помощью оператора offset получаем адрес процедуры sum и загружаем его в регистр RAX. Затем для вызова процедуры передаем регистр RAX инструкции call. Также можно было бы использовать инструкцию lea

lea rax, sum  ; загружаем адрес процедуры sum

При сохранении адреса в переменную она должна представлять тип qword:

.data
ptrToSum qword offset sum   ; указатель содержит адрес процедуры sum
.code
sum proc
    mov rax, rcx
    add rax, rdx
    ret
sum endp

main proc
    mov rcx, 22
    mov rdx, 25
    call ptrToSum   ; вызываем процедуру через указатель
    ret
main endp
end

Здесь получаем адрес сразу при определении переменной-указателя. Но можно также динамически получать адрес процедуры в программе:

lea rax, sum
mov ptrToSum, rax
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850