CALL <метка> – Вызов подпрограммы
Команда call передает управление подпрограмме, сохранив перед этим в стеке адрес точки возврата. Команда ret, которой обычно заканчивается подпрограмма, извлекает из стека адрес точки возврата и возвращает управление на команду, следующую за командой call. Команда call не воздействует на флаги процессора.
Команда call имеет четыре модификации:
· вызов прямой ближний (в пределах текущего программного сегмента);
· вызов прямой дальний (вызов подпрограммы, расположенной в другом программном сегменте);
· вызов косвенный ближний;
· вызов косвенный дальний.
Все разновидности вызовов имеют одну и ту же мнемонику call, хотя и различающиеся коды операций. Во многих случаях транслятор может определить вид вызова по контексту, в тех же случаях, когда это невозможно, следует использовать атрибутные операторы:
near ptr – прямой ближний вызов;
far ptr – прямой дальний вызов;
word ptr – косвенный ближний вызов;
dword ptr – косвенный дальний вызов.
Команда call прямого ближнего вызова заносит в стек относительный адрес точки возврата в текущем программном сегменте и модифицирует IP так, чтобы в нем содержатся относительный адрес точки перехода в том же программном сегменте. Необходимая для вычисления этого адреса величина смещения от точки возврата до точки перехода содержится в коде команды, который занимает 3 байт (код операции E8h и смещение к точке перехода).
|
|
Команда call прямого дальнего вызова заносит в стек два слова – сначала сегментный адрес текущего программного сегмента, а затем (выше, в слово с меньшим адресом) относительный адрес точки возврата в текущем программном сегменте. Далее модифицируются регистры IP и CS: в IP помещается относительный адрес точки перехода в том сегменте, куда осуществляется переход, а в CS – сегментный адрес этого сегмента. Обе эти величины берутся из кода команды, который занимает 5 байт (код операции 9Аh, относительный адрес вызываемой подпрограммы и ее сегментный адрес).
Косвенные вызовы отличаются тем, что адрес перехода извлекается не из кода команды, а из ячеек памяти; в коде команды содержится информация о том, где находится адрес вызова. Длина кода команды зависит от используемого способа адресации.
RET – Возврат из процедуры
RETN – Возврат из ближней процедуры
RETF – Возврат из дальней процедуры
Команда ret извлекает из стека адрес возврата и передает управление назад в программу, первоначально вызвавшую процедуру. Если командой ret завершается ближняя процедура, объявленная с атрибутом near, или используется модификация команды retn, со стека снимается одно слово– относительный адрес точки возврата. Передача управления в этом случае осуществляется в пределах одного программного сегмента. Если командой ret завершается дальняя процедура, объявленная с атрибутом far, или используется модификация команды retf, со стека снимаются два слова: смещение и сегментный адрес точки возврата. В этом случае передача управления может быть межсегментной.
|
|
В команду ret может быть включен необязательный операнд (кратный 2), который указывает, на сколько байтов дополнительно смещается указатель стека после возврата в вызывающую программу. Прибавляя эту константу к новому значению SP, команда ret обходит аргументы, помещенные в стек вызывающей программой (для передачи процедуре) перед выполнением команды call. Обе разновидности команды не воздействуют на флаги процессора.
Jcc <метка> – Команды условных переходов
Команды, обозначаемые (в книгах, не в программах!) Jcc, осуществляют переход по указанному адресу при выполнении условия, заданного мнемоникой команды. Если заданное условие не выполняется, переход не осуществляется, а выполняется команда, следующая за командой Jcc. Переход может осуществляться как вперед, так и назад в диапазоне +127...-128 байт.
В составе команд процессора предусмотрены следующие команды условных переходов:
Таблица 25 – Условия перехода
Команда | Условие перехода |
ja | выше CF=0 и ZF=0 |
jae | выше или равно CF=0 |
jb | ниже CF=1 |
jbe | ниже или равно CF=1 или ZF=1 |
jc | перенос CF=1 |
jcxz | CX=0 |
je | равно ZF=1 |
jg | больше ZF=0 или SF=OF |
jge | больше или равно SF=OF |
jl | меньше SF не равно OF |
jle | меньше или равно ZF=1 или SF не равно OF |
jna | не выше CF=1 или ZF=1 |
jnae | не выше и не равно CF=1 |
jnb | не ниже CF=0 |
jnbe | не ниже и не равно CF=0 и ZF=0 |
jnc | нет переноса CF=0 |
jne | не равно ZF=0 |
jng | не больше ZF=1 или SF не равно OF |
jnge | не больше и не равно SF не равно OF |
jnl | не меньше SF=OF |
jnle | не меньше и не равно ZF=0 и SF=OF |
jno | нет переполнения OF=0 |
jnp | нет четности PF=0 |
jns | знаковый бит равен О SF=0 |
jnz | не нуль ZF=0 |
jo | переполнение OF=1 |
jp | есть четность PF=1 |
jpe | сумма битов четная PF=1 |
jpo | сумма битов нечетная PF=0 |
js | знаковый бит равен SF=1 |
jz | нуль ZF= I |
Команды условных переходов, осуществляющие переход по условию "выше – ниже", предназначены для анализа чисел без знака; команды, осуществляющие переход по условию "больше – меньше", предназначены для анализа чисел со знаком.
JMP <метка> – Безусловный переход
Команда jmp передает управление в указанную точку того же или другого программного сегмента. Адрес возврата не сохраняется. Команда не воздействует на флаги процессора.
Команда jmp имеет пять разновидностей:
– переход прямой короткий (в пределах -128... + 127 байтов);
– переход прямой ближний (в пределах текущего программного сегмента);
– переход прямой дальний (в другой программный сегмент);
– переход косвенный ближний;
– переход косвенный дальний.
Все разновидности переходов имеют одну и ту же мнемонику jmp, хотя и различающиеся коды операций. Во многих случаях транслятор может определить вид перехода по контексту, в тех же случаях, когда это невозможно, следует использовать атрибутные операторы:
short – прямой короткий переход;
near ptr – прямой ближний переход;
far ptr – прямой дальний переход;
word ptr – косвенный ближний переход;
dword ptr – косвенный дальний переход.
INT <число> – Программное прерывание
Команда int инициирует в процессоре процедуру прерывания, в результате которой управление передается на обработчик прерывания с номером, который указан в качестве операнда команды int. В стек текущей программы заносится содержимое регистра флагов, сегментного регистра CS и указателя команд IP, после чего в регистры IP и CS передается содержимое двух слов из вектора прерывания с номером n (расположенных по адресам 0:n*4 и 0:n*4+2). Команда сбрасывает флаги IF и TF в 0. Команда iret, которой всегда завершается обработчик прерывания, восстанавливает исходное состояние этих флагов.
|
|
INTO – Прерывание по переполнению
Команда into, будучи установлена вслед за какой-либо арифметической, логической или строковой командой, вызывает обработчик прерываний через вектор 4, если предшествующая команда установила флаг переполнения OF. Перед использованием команды INTO прикладной программист должен поместить в вектор прерывания 4 двухсловный адрес своей программы обработки прерывания по переполнению. Команда сбрасывает флаги IF и TF в 0. Команда iret, которой всегда завершается обработчик прерывания, восстанавливает исходное состояние этих флагов.
IRET – Возврат из прерывания
Команда iret возвращает управление прерванному в результате аппаратного или программного прерывания процессу. Команда извлекает из стека три верхние слова и помещает их в регистры IP, CS и флагов (см. команду int). Командой iret должен завершаться любой обработчик прерываний, как аппаратных, так и программных (от команды int). Команда не воздействует на флаги, однако она загружает в регистр флагов из стека его исходное содержимое, которое было там сохранено процессором в процессе обслуживания прерывания. Если требуется, чтобы после возврата из обработчика программного прерывания командой iret какие-либо флаги процессора были установлены требуемым образом (весьма распространенный прием), их установку надо выполнить в копии флагов в стеке.