На главную Назад
Добро пожаловать, уважаемый посетитель!

Существует несколько команд условного перехода, предназначенных для

управления циклами в программах.Поскольку программые циклы

используются часто, желательно эффективное управление циклом.На

Фиг. 4.30 показаны четыре команды, созданные для того, чтобы

облегчить программирование циклов на языке ассемблера

микропроцессора 8088.

 

Так же, как строковые команды используют регистр CX в качестве

счетчика, команды цикла LOOP используют регистр CX в качестве

счетчика цикла. Все эти команды неявно рассматривают регистр CX как

счетчик итераций цикла. Простейшая команда среди них - команда

LOOP. Команда LOOP уменьшает регистр CX и передает управление на

метку, если содержимое регистра CX не равно 0. Если вычитание

единицы из регистра CX не привело к нулевому результату, команда

LOOP не делает перехода, и выполняется следующая команда.

 

Приведенный ниже программный фрагмент демонстрирует обычное

использование команды LOOP.

 

MOVCX,LOOP_COUNT

BEGIN_LOOP:

; ...тело цикла

LOOPBEGIN_LOOP

 

Microsoft (R) Macro Assembler Version 5.001/1/80 04:02:01

Фиг. 4.30 Команды циклаPage 1-1

 

 

PAGE,132

TITLEФиг. 4.30 Команды цикла

 

0000CODESEGMENT

ASSUMECS:CODE

 

;----------------------------------------

; В этом примере демонстрируются команды цикла.

; Команды в примере не являются законченной программой.

;----------------------------------------

 

0000E3 06JCXZEND_OF_LOOP; Конец цикла, если CX равно 0

 

0002BEGIN_LOOP:

 

; ....Тело цикла

 

0002E2 FELOOPBEGIN_LOOP; Переход пока регистр CX не станет равен 0

 

; ....Если проверяется какое-либо условие, то

0004E1 FCLOOPEBEGIN_LOOP; Переход по равенству в условии и

;значение регистра CX не равно 0

; ....Или

 

0006E0 FALOOPNEBEGIN_LOOP; Переход по неравенству в условиии и

;значение регистра CX не равно 0

 

0008END_OF_LOOP:

 

0008CODEENDS

END

 

Фиг. 4.30 Команда цикла

 

Программа помещает число итераций цикла в регистр CX перед

выполнением цикла. Затем выполняется тело цикла, а следом за ним

команда LOOP. Она уменьшает счетчик на единицу, что соответствует

единственной, только что выполненной итерации цикла. Если теперь

счетчик в регистре CX равен 0, программа продолжает выполняться

после команды LOOP. Если счетчик не равен 0, управление

возвращается к началу цикла, чтобы совершить еще один проход по

телу цикла. Тело цикла выполняется столько раз, сколько было

сначала задано содержимым регистра CX. Единственное важное

замечание: если программа внутри цикла изменяет регистр CX, число

итераций цикла не будет соответствовать начальному значению в

регистре CX.

 

Описанный метод одинаково хорошо работает, когда число циклов

известно во время ассемблирования (как в примере, где LOOP_COUNT -

непосредственно заносимое значение), и когда число циклов

определяется во время выполнения. Если вычисленное число оказалось

равным 0, цикл выполнится 65536 раз. Когда микропроцессор 8088

выполняет первую команду LOOP, он уменьшает CX от 0 до 0FFFFH, и

поскольку теперь регистр CX ненулевой, повторяет цикл. Таким

образом, загрузка нулевого значения счетчика циклов - специальный

случай. Этот специальный случай обрабатывается командой JCXZ

(переход, если содержимое регистра CX равно 0). Эта команда

проверяет текущее содержимое регистра CX, и делает переход, если

оно равно нулю. Команда не проверяет ни одного флага, и не влияет

ни на один из них. Следующий пример аналогичен предыдущему, за

исключением того, что он загружает регистр CX из ячейки памяти,

содержимое которой вычисляется во время выполнения программы. По

этой причине может оказаться, что счетчик циклов нулевой, и пример

использует команду JCXZ, чтобы проверить, нужно ли полностью

пропустить тело цикла.

 

MOVCX,LOOP_COUNT_WORD

JCXZEND_OF_LOOP

BEGIN_LOOP:

;... тело цикла

LOOPBEGIN_LOOP

END_OF_LOOP:

 

В программе не нужно использовать команду JCXZ в каждом цикле с

вычисляемым счетчиком. Если программист знает, что счетчик циклов

никогда не будет равен нулю, проверка не нужна. Однако опыт

показывает, что значение, которое "никогда" не должно появиться,

обычно появляется в первую очередь, как только вы начинаете

выполнять программу.

 

Оставшиеся две команды цикла предоставляют еще большие

возможностей при управлении циклами. Эти команды аналогичны

префиксам REPE и REPNE. Если команда LOOP выходит из цикла, только

когда в регистре CX оказывается нуль, то команда LOOPE (цикл, пока

равно) выходит из цикла, если установлен флаг нуля, или если в

регистре CX получился 0. Тем самым становится возможным

двойственное завершение цикла. Программа может загрузить в регистр

CX максимальное число итераций цикла, а затем проверять флаг нуля в

конце каждого цикла на условие завершения. Команда LOOPNE (цикл,

пока не равно) выполняет обратную к описанной проверку флага нуля:

цикл здесь завершается, если регистр достиг нуля, или если

установлен флаг нуля.

Следующий пример показывает использование команды LOOPNE. В

примере складываются два списка чисел, чтобы найти пару элементов,

сумма которых точно равна 100. Так как в каждой итерации перед

проверкой складываются два чила, команду REPNE CMPSB использовать

нельзя.

 

В примере предполагается, что пары регистров DS:SI и ES:DI

инициализированы так, чтобы указывать на эти списки.

 

MOVCX,MAX_LOOP_COUNT ;максимальное число заходов

BEGIN_LOOP:

LODSB;чтение числа из первого списка

ADDAL,ES:[DI];прибавить из второго списка

INCDI;указатель на следующий элемент

CMPAL,100;проверка на нужное значение

LOOPNEBEGIN_LOOP;снова, если не равно и не все

JEMATCH_FOUND;переход сюда, чтобы определить конец


 

Mail.ru