Косвенный ближний вызов. Адрес подпрограммы содержится либо в ячейке памяти, либо в регистре. Это позволяет, как и в случае косвенного ближнего перехода, модифицировать адрес вызова, а также осуществлять вызов не с помощью метки, а по известному абсолютному адресу. Структура программы с косвенным вызовом подпрограммы может выглядеть следующим образом:
code segment
main proc ;Основная программа
…
call DS:subadr ;Код FF 16 dddd
main endp
subr proc near ;Подпрограмма
…
ret ;Код СЗ
subr endp
code ends
data segment
…
subadr dw subr ;Яейка с адресом подпрограммы
data ends
Процедура-программа с атрибутом near находится в том же сегменте, что и вызывающая программа, а ее относительный адрес в ячейке subadr в сегменте данных. В коде команды dddd обозначает относительный адрес слова subadr в сегменте данных. Второй байт кода команды (16h в данном примере) зависит от способа адресации. Косвенный вызов позволяет использовать разнообразные способы адресации подпрограммы:
call BX ; В ВХ адрес подпрограммы
call[BX] ; В ВХ адрес ячейки с адресом подпрограммы
call[BX][SI] ;В ВХ адрес таблицы адресов подпрограмм,
;в SI индекс в этой таблице.
tbl[SI] ;tbl - адрес таблицы адресов подпрограмм,
;в SI индекс в этой таблице
Косвенный дальний вызов. Отличается от косвенного ближнего вызова лишь тем, что подпрограмма находится в другом сегменте, а в ячейке памяти содержится полный адрес подпрограммы, включающий сегмент и смещение.
codel segment
main proc ;Основная программа
call dword ptr subadr ;Код FF IE dddd
…
main endp
codel ends
code2 segment
subr proc far ;Подпрограмма
…
ret ;Код СВ
subr endp
code2 ends
data segment
…
subadr dd subr ;Двухсловная ячейка с
;адресом подпрограммы
data ends
Процедура-подпрограмма с атрибутом far находится в другом сегменте команд той же программы, а ее полный двухсловный адрес - в ячейке subadr в сегменте данных. Второй байт кода команды (IE в данном примере) зависит от способа адресации. Косвенный дальний вызов, как и косвенный ближний, позволяет использовать различные способы адресации.