Команды организации циклов
В практике программирования наиболее часто встречаются циклы с заранее известным числом итераций. Поэтому в системе команд микропроцессора 8086 доступны команды управления циклом, упрощающие реализацию подобных циклов. Цикл с известным числом итераций можно реализовать по схеме:
MOV CX, N ; CX - счетчик цикла (число повторений)
L: ...
... ; тело цикла
DEC CX ; СХ=СХ-1
CMP CX, 0 ; СХ=0?
JNE L ; СХ<>0 > goto L
В конце цикла всегда применяется одна и та же тройка команд. Команда LOOPобъединяет действия трех команд и позволяет организовать цикл по счётчику (табл. 52). Флаги команда не изменяет. В качестве счётчика всегда используется регистр CX.
Табл. 52. Команда LOOP.
Код | Инструкция | Описание |
E2 cb | LOOP rel8 | Цикл по счётчику. |
E1 cb | LOOPE rel8 | Цикл по счётчику и равенству. |
E1 cb | LOOPZ rel8 | Цикл по счётчику и нулевому результату. |
E0 cb | LOOPNE rel8 | Цикл по счётчику и неравенству. |
E0 cb | LOOPNZ rel8 | Цикл по счётчику и ненулевому результату. |
Действие команды LOOP можно представить следующим образом:
CX=CX-1;
if СХ<>0 then goto <метка>
С помощью команды LOOP цикл запишется так:
MOV CX, N ; N > 0
L: ...
... ; тело цикла
LOOP L
Команда LOOP работает быстрее трех предыдущих команд, однако существует ряд особенностей:
- В качестве счетчика цикла можно использовать только регистр СХ.
- Начальное значение для СХ должно быть присвоено до цикла, причем этому регистру надо присваивать ровно столько, сколько должен повторяться цикл. Команда LOOP контролирует только нулевое значение, при отрицательном значении цикл не завершится.
- Минимальное число итераций равно одному. Для случая СХ=0 команда не подходит.
Если число итераций может быть нулевым, то при СХ=0 надо выполнить обход цикла:
MOV CX, N
JCXZ L1
L: ...
... ; тело цикла
LOOP L
L1:...
Для выполнения таких обходов существует команда условного перехода JCXZ.
Дополнительным условием продолжения выполнения цикла может быть состояние флага ZF в 0 (LOOPNE, LOOPNZ) или 1 (LOOPE, LOOPZ). Названия LOOPE и LOOPZ являются синонимами, также как LOOPNE и LOOPNZ.
Действие этих команд следующее:
СХ:=СХ-1;
If (CX <> 0) and (ZF = 1) then goto <метка>
Команда LOOPE используется для организации цикла с известным числом итераций, из которого возможен досрочный выход. До начала цикла в регистр СХ записывается число итераций. Команда помещается в конец цикла (операнд команды – метка первой команды цикла), а перед ней помещается команда, меняющая флаг ZF (обычно команда сравнения СМР). Команда LOOPE заставляет цикл повторяться СХ раз, но только если предыдущая команда фиксирует равенство сравниваемых величин (вырабатывает нулевой результат).
Причину выхода (ZF=1 или СХ=0) следует проверять после цикла. Причем проверяется флаг ZF (по команде JE/JZ или JNE/JNZ), а не регистр СХ, т.к. условие ZF=0 может появиться на последнем шаге цикла, когда регистр СХ стал нулевым.
Команда LOOPNE/LOOPNZ аналогична команде LOOPE/LOOPZ, но выход из цикла осуществляется при СХ=0 или ZF=0. Действие команды:
СХ:=СХ-1;
if (CX <> 0) and (ZF = 0) then goto <метка>
Приведем пример использования команды цикла. Предположим, требуется найти в некоторой области памяти первый ненулевой байт. Смещение начального адреса находится в регистре SI, конечного – в регистре DI. Смещение найденного байта возвращается в регистр SI. Если ненулевой байт не найден, SI, будет указывать на конец области памяти, т.е. содержать тоже значение, что и DI.
SUB DI, SI ; размер области памяти
INC DI ; DI=DI-SI+1
MOV CX, DI ; счетчик байтов
DEC SI
L: INC SI ; переместить указатель к следующей ячейке
CMP BYTE PTR [SI], 0 ; сравнить содержимое ячейки с нулем
LOOPZ L ; переход к проверке следующего байта
JNZ L1 ; переход по метке L1, если байт ненулевой
... ; ненулевой байт не найден
L1:... ; смещение ненулевого байта находится в SI
Также как и команды условного перехода, все инструкции циклов выполняют только короткие переходы, поскольку в них используется относительная адресация с 8-разрядным отклонением. Если цикл содержит больше команд, команду цикла использовать не получится и цикл следует реализовать по-иному.