Иллюстрированный самоучитель по Assembler

C

CALL Вызов подпрограммы

Команда call передает управление подпрограмме, сохранив перед этим в стеке смещение к точке возврата. Команда ret, которой обычно заканчивается подпрограмма, забирает из стека адрес возврата и возвращает управление на команду, следующую за командой call. Команда не воздействует на флаги процессора.

Команда call имеет четыре модификации:

  • вызов прямой ближний (в пределах текущего программного сегмента);
  • вызов прямой дальний (вызов подпрограммы, расположенной в другом программном сегменте);
  • вызов косвенный ближний;
  • вызов косвенный дальний.

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

  • near ptr – прямой ближний вызов;
  • far ptr – прямой дальний вызов;
  • word ptr – косвенный ближний вызов;
  • dword ptr – косвенный дальний вызов.

Команда call прямого ближнего вызова заносит в стек относительный адрес точки возврата в текущем программном сегменте и модифицирует IP так, чтобы в нем содержатся относительный адрес точки перехода в том же программном сегменте. Необходимая для вычисления этого адреса величина смещения от точки возврата до точки перехода содержится в коде команды, который занимает 3 байт (код операции E8h и смещение к точке перехода).

Команда call прямого дальнего вызова заносит в стек два слова – сначала сегментный адрес текущего программного сегмента, а затем (выше, в слово с меньшим адресом) относительный адрес точки возврата в текущем программном сегменте. Далее модифицируются регистры IP и CS: в IP помещается относительный адрес точки перехода в том сегменте, куда осуществляется переход, а в CS – сегментный адрес этого сегмента. Обе эти величины берутся из кода команды, который занимает 5 байтов (код операции 9А1г, относительный адрес вызываемой подпрограммы и ее сегментный адрес).

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

Примеры прямого ближнего вызова:

call near ptr subl; Вызов подпрограммы subl
;из того же сегмента
call subl; To же самое

Косвенные ближние вызовы.
Пример 1:

mov BX,offset subl; ВХ=адрес подпрограммы
call BX; Вызов подпрограммы

Пример 2:

; В полях данных:
addr dw subl; Ячейка с адресом подпрограммы
;В программном сегменте:
call DS:addr; Вызов подпрограммы
call word ptr addr; To же самое

Пример 3:

;В полях данных:
addr dw subl; Ячейка с адресом подпрограммы
;В программном сегменте:
mov SI,offset addr; SI=адрес ячейки с адресом
;подпрограммы
call [SI]; Вызов подпрограммы

Пример 4:

;В полях данных:
tbl dw subl; Ячейка с адресом
;подпрограммы 1
dw sub2; Ячейка с адресом
;подпрограммы 2
dw sub3; Ячейка с адресом
;подпрограммы 3
;В программном сегменте:
mov BX,offset tbl; ВХ=адрес таблицы адресов подпрограмм
mov SI, 2; SI=смещение к адресу sub2
call [BX] [SI]; Вызов подпрограммы 2
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.