Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ВС сети и телекомм-практикум.doc
Скачиваний:
45
Добавлен:
01.07.2025
Размер:
614 Кб
Скачать
☆

4. Команды передачи управления и управления флагами

В этом разделе изучим команды передачи управления и управления флагами.

Простейшими командами передачи управления являются команды безусловного и условного переходов. Команда JMP (джампер, от слова прыжок), является командой безусловного (обязательного) перехода. имеющей формат

JMP операнд.

JMP передает управление в другую точку программы, не сохраняя какой-либо информации для возврата. Операндом в большей части случаев является метка, установленная перед командой, на которую выполняется переход. Иногда используют регистр или переменную, содержащие адрес перехода.

Необходимо помнить, что переход может быть нескольких видов:

- short (короткий переход) – если адрес перехода находится в пределах от -127 до +128 байт от команды JMP;

- near (ближний переход) – если адрес перехода находится в том же сегменте памяти, что и команда JMP;

- far (дальний переход) – если адрес перехода находится в другом сегменте. Дальний переход может выполняться и в тот же самый сегмент, если в сегментной части операнда указано число, совпадающее с текущим значением сегментного регистра кода CS.

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

Безусловный переход представлен лишь одной командой, в то время как команд условно перехода гораздо больше. Все команды условного перехода выполняют переход (типа short или near), если выполняется соответствующее условие. Условием в каждом случае реально является состояние тех или иных флагов. Если же условие не выполняется, то команда игнорируется и мы идем дальше по программе. Формат любой из команд условного перехода имеет следующий вид:

Jxx метка.

В тексте программы это может выглядеть так:

m1:

…

…

JNZ m1

Иными словами, если результат предидущих действий не равен нулю, то выполняется переход на метку m1. Если же наблюдается равенство нулю, то игнорируем команду условного перехода и идем дальше по программе.

Следует помнить, что команды типа Jxx не поддерживают дальних переходов, так что, если требуется выполнить условный переход на дальнюю метку, необходимо использовать команду из набора Jxx с обратным условием и дальний JMP.

Теперь перечислим команды условного перехода:

- 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.

- JZ – переход если ноль. Полный аналог JE.

- JG – переход, если больше, то есть первый операнд больше второго. Выполняется, если SF=OF, ZF=0. Очень похожа на команду JA, различие лишь в одном из двух условий по флагам.

- JGE - переход, если больше, , то есть первый операнд больше либо равен второму. Выполняется, если SF=OF. Очень похожа на команду JAE.

- JL – переход, если меньше, то есть первый операнд меньше второго. Выполняется, если SF≠OF. Очень похожа на команду JВ.

- JLE – переход, если меньше или равно, то есть первый операнд меньше либо равен второму. Выполняется, если SF≠OF или ZF=1. Очень похожа на команду JВЕ.

- JNA – переход, если не выше. Полный аналог JBE.

- JNAE – переход, если не выше и не равно. Полный аналог JB.

- JNB – переход, если не ниже. Полный аналог JAE.

- JNВE – переход, если не ниже и не равно. Полный аналог JА.

- JNC – переход осуществляется, если флаг переноса сброшен (CF=0).

- JNE – переход, если не равно, то есть первый операнд не равен второму. Выполняется, если ZF=0.

- JNL – переход, если не меньше. Полный аналог JGE.

- JNLЕ – переход, если не меньше и не равно. Полный аналог JG.

- JNO – переход осуществляется, если сброшен флаг переполнения (OF=0).

- JO – переход осуществляется, если установлен флаг переполнения (OF=1).

- JNP – переход, если нечетно, то есть флаг четности сброшен (PF=0).

- JPO – переход, если нечетно. Полный аналог JNP.

- JP – переход, если четно, то есть флаг четности установлен (PF=1).

- JPЕ – переход, если четно. Полный аналог JP.

- JNS – переход, если результат не является отрицательным. Выполняется, если флаг знака SF=0.

- JS – переход, если результат является отрицательным. Выполняется, если флаг знака SF=1.

- JNZ – переход, если не ноль. Полный аналог JNE.

- JNG – переход, если не больше. Полный аналог JLE.

- JNGE – переход, если не больше и не равно. Полный аналог JL.

По мнению автора, ассемблер перенасыщен командами условного перехода, и это даже не учитывая абсолютно идентичные по действию пары команд. Поэтому рекомендуется использовать лшь те из них, которые представляются тому или иному пользователю наиболее эффетивными и удобными. Естественно, не следует заучивать их все наизусть. Достаточно иметь общее представление о принципах работы данного типа команд.

Следующая рассматриваемая нами команда и ее разновидности является основным и наиболее эффективным инструментом ассемблера для реализации циклов. Это переход по счетчику LOOP. Формат команды:

LOOP метка

Суть заключается в том, что данная команда уменьшает значение регистра счетчика на единицу, то есть CX=CX-1. После этого уменьшения мы передаем управление по метке, если только значение счетчика не стало равным нулю (CX=0). В тексте программы это может выглядеть следующим образом:

…

MOV CX, 5

m1:

ADD AX, 3

LOOP m1

…

Здесь мы создаем цикл из пяти шагов-повторений, записывая перед его началом в регистр счетчик CX число 5. Каждый раз, когда команда LOOP будет переносить нас на метку m1, выполняется сложение содержимого регистра AX и числа 3. Как только проходит заданное число шагов, цикл считается завершенным, и мы выходим из него, следуя дальше по программе.

Следующие вариации команды LOOP представляют собой:

- LOOPE – цикл, пока равно, то есть если первый операнд ранее выполненной вычисляющей команды был равен второму. Выполняется, если CX≠0, флаг знака ZF=1

- LOOPNE – цикл, пока не равно, то есть если первый операнд ранее выполненной вычисляющей команды не был равен второму. Выполняется, если CX≠0, флаг знака ZF=0

- LOOPZ – цикл, пока ноль. Полный аналог LOOPE.

- LOOPNZ – цикл, пока не ноль. Полный аналог LOOPNE

Теперь разберемся с парой команд CALL и RET. Первая из них осуществляет вызов подпрограммы, сохраняя текущий адрес в стеке и передавая управление по адресу, указанному в операнде. Операндом может быть метка, регистр или переменная, содержащие адрес перехода.

CALL имя подпрограммы

Следует отметить, что вызов подпрограммы может быть ближним (NEAR), что происходит по умолчанию, и дальним (FAR), когда вызываемая подпрограмма находится вне указанного сегмента. Если в качестве адреса перехода указано только смещение, считается, что адрес расположен в том же сегменте, что и команда CALL. Выполняется ближний вызов процедуры. Процессор помещает значение программного регистра указателя IP, соответствующее следующей за CALL команде, в стек и загружает в IP новое значение, осуществляя тем самым передачу управления.

В случае, если осуществляется дальний вызов (FAR), то процессор сначала заносит в стек текущее значение сегментного регистра кода CS, затем текущее значение IP, а потом уже передает управление вызываемой подпрограмме.

Вторая команда из пары, то есть RET, осуществляет возврат из подпрограммы, передавая управление команде, которая следует сразу же за CALL. Теоретически у команды возврата из подпрограммы есть две разновидности – RETN и RETF. Они соответствую, как понятно из названия, ближнему и дальнему вызову.

RETN считывает из стека и загружает его в IP, выполняя тем самым действия, обратные ближнему вызову процедуры командой, CALL. RETF соответственно загружает из стека IP и CS, возвращаясь из дальней процедуры. Если в программе указана команда RET, ассемблер заменит ее на RETN или RETF в зависимости от того, как была описана процедура, которую эта команда завершает.

Закончив с командами передачи управления, рассмотрим команды управления флагами. Отметим, что все они не нуждаются в операндах и не меняют ничего, кроме значения конкретного флага, с которым ассоциированы.

С флагом переноса CF работают следующие команды:

- STC – устанавливает флаг переноса равным 1.

- СLC – сбрасывает флаг переноса в 0.

- CMC – инвертирует флаг переноса. То есть если он был равен 0, то станет равным 1 и наоборот.

С флагом направления DF работают команды:

- STD – устанавливает флаг направления равным 1. Это влечет за собой уменьшение индексных регистров SI и DI и чаще всего применяется в командах обработки строк.

- CLD – сбрасывает флаг направления в 0. Это влечет за собой увеличение индексных регистров SI и DI.

С флагом прерываний IF работают команды:

- STI – устанавливает флаг прерывания равным 1, разрешая процессору работать с прерываниями от внешних устройств.

- CLI – сбрасывает флаг прерывания в 0. Это влечет за собой то, что процессор перестает воспринимать любые прерывания от внешних устройств.

Помимо перечисленных, есть и другие команды. Работающие с флагами, такие как:

- LAHF – загружает флаги состояния в AH. Иными словами, в АН копируется младший байт регистра-аккумулятора, включающий в себя флаги основного и дополнительного переноса (CF, AF), четности (PF), нуля (ZF) и знака (SF).

- SAHF – загружает флаги SF, ZF, AF, PF и CF из AH.

- PUSHF – копирует содержимое регистра флагов в стек.

- POPF – считывает значение из вершины стека и помещает его в регистр флагов.

Разобрав работу команд, управляющих состоянием флагов, не будем игнорировать и более редкие управляющие команды.

NOP – команда, которая не делает ничего, только занимает место и процессорное время. Используется в целях подгонки времени и для выравнивания памяти.

LOCK – блокирует шину данных. Пока эта команда действует, шина заблокирована. Используется в тех случаях, когда требуется запретить другому (другим) процессорам обращаться к памяти.

ESC – используется в случаях, когда необходимо передать управление внешнему процессору.

HLT – останавливает процессор. Он будет находиться в ожидании до получения специального сигнала сброса или немаскированного прерывания.