- •3.11.1 Команды пересылки данных
- •Команды пересылки общего назначения
- •Xchg приемник, источник
- •Команды загрузки адресных значений
- •Команды обращения к стеку
- •Команды пересылки флагов
- •Команды ввода/вывода
- •In аккумулятор, порт
- •In аккумулятор, dx.
- •3.11.2. Арифметические команды
- •Типы арифметических данных
- •Команды инкрементирования и декрементирования
- •Inc приемник
- •Команды сложения и вычитания
- •Команды расширения знака
- •Команды умножения и деления
- •Imul источник.
- •Команды десятичной коррекции
- •Сложение в bdc-формате
- •Вычитание в bcd-формате
- •Сложение в ascii-формате
- •Вычитание в ascii-формате
- •Умножение в ascii-формате
- •Деление в ascii-формате
- •3.11.3 Логические команды
- •Команды логических операций
- •Команды сравнения
- •Команды сдвигов
- •Команды логических сдвигов
- •Команды арифметических сдвигов
- •Команды циклических сдвигов
- •3.11.4. Команды передачи управления
- •Команды безусловных переходов
- •Команды условных переходов
- •Команды перехода по состоянию арифметических флагов
- •Команды перехода по соотношению между числами
- •Команды перехода по состоянию регистра cx
- •Команды управления циклами
- •Команды для организации подпрограмм
- •Команды прерываний
- •3.11.5. Команды обработки строк
- •Строковые примитивы
Команды перехода по состоянию регистра cx
К этой подгруппе относится единственная команда JCXZ, которая передает управление по указанной метке, если (CX)=0.
Эта команда используется для организации циклов в тех случаях, когда возможна ситуация, в которой тело цикла не выполняется ни разу. При этом команда JCXZ помещается перед телом цикла и передает управление за его пределы.
Пример 3.95:
MOV CX,Count ; Чтение счетчика циклов
JCXZ EndLoop ; Переход, если счетчик=0
. . . . . . . . . ; Тело цикла
. . . . . . . . .
EndLoop: . . . . . . . . . ; Продолжение программы
; при (Count)=0
Очень часто в программах необходимо совершать условные переходы за пределы короткого диапазона (полные внутрисегментные переходы, межсегментные переходы). Такие условные переходы реализуются командами JMP, выполняемыми при истинности противоположного условия.
Пример 3.96:
Выполнить межсегментный условный переход на метку Zero при флаге нуля ZF=1:
JNZ Cont ; Анализ противоположного условия ZF=0
JMP FAR PTR Zero ; Межсегментный переход при ZF=1
Cont:. . . . . . . . . . . . ; Продолжение программы при ZF=0
Команды управления циклами
Команды управления циклами используются для условной передачи управления при организации циклов. Они записываются в формате:
LOOPcond Labl,
где cond дополнительное формальное условие перехода.
При этом основным проверяемым условием для всех команд является содержимое счетчика циклов, в качестве которого служит регистр CX. Каждая команда управления циклами прежде всего декрементирует регистр CX, а затем анализирует его. Если (CX)< >0, то управление передается на начало цикла по указанной метке Labl. Если (CX)=0, то выполняется очередная команда программы.
Все переходы, реализуемые командами управления циклами, являются короткими. Это также обусловлено тем, что их машинный код содержит лишь один байт для хранения дистанции disp8, который используется при вычислении адреса перехода (IP)=(IP)+disp8(Labl).
Дополнительное условие перехода cond либо отсутствует в команде, либо сводится к анализу флага ZF и принимает значения Z/E или NZ/NE.
Основной командой этой подгруппы является команда LOOP, в которой дополнительное условие перехода отсутствует. Она записывается в формате:
LOOP Labl.
Команда LOOP повторяет цикл, пока (CX)< >0 и завершает его при (CX)=0. Она используется для организации циклов с постусловием. При этом фрагмент программы имеет вид:
MOV CX, Count ; Загрузка счетчика циклов
Begin:. . . . . . . . . ; Тело цикла
. . . . . . . . .
LOOP Begin ; Зацикливание, если (CX)< >0
. . . . . . . . . ; Продолжение программы
Пример 3.97:
Выполнить зеркальную перестановку битов в регистре AL (см. пример 3.90).
MOV CX, 8 ; Загрузка счетчика циклов
Next: RCL AL, 1 ; Выделение бита
RCR DL, 1 ; Формирование результата
LOOP Next
MOV AL, DL ; Пересылка результата
Во многих приложениях требуются такие циклы, которые должны завершаться не только после заданного количества повторений, но и при выполнении какого-либо другого условия. В качестве дополнительного условия прекращения цикла чаще всего используется значение флага ZF.
Для организации таких циклов предназначены команды LOOPZ/LOOPE и LOOPNZ/LOOPNE. Как правило, они используются после команды сравнения CMP.
Команда LOOPZ/LOOPE повторяет цикл до тех пор, пока (CX)< >0 и ZF=1. Следовательно, цикл завершается, если либо (CX)=0, либо ZF=0. Обычно эта команда применяется для организации циклов с целью поиска первого несовпадающего элемента в некотором массиве.
Команда LOOPNZ/LOOPNE повторяет цикл до тех пор, пока (CX)< >0 и ZF=0. Следовательно, цикл завершается, если либо (CX)=0, либо ZF=1. Обычно эта команда применяется для организации циклов с целью поиска первого совпадающего элемента в некотором массиве.
Таким образом, команды LOOPZ/LOOPE и LOOPNZ/LOOPNE допускают два варианта завершения цикла. Вариант завершения легко определить путем анализа состояния флага ZF после выхода из цикла. Например, если после завершения цикла командой LOOPNZ/LOOPNE оказывается, что ZF=1, то цикл завершен по совпадению элементов, а при ZF=0 по счетчику цикла, так как совпадений не было.
Пример 3.98:
Найти первый нулевой элемент в массиве байтов Array:
LEA BX, Array1 ; Загрузка адреса и
MOV CX, LENGTH Array ; счетчика циклов
Next: INC BX ; Модификация адреса
CMP BYTE PTR [BX], 0 ; Сравнение с нулем
LOOPNZ Next
JNZ NotFound ; Переход, если нуль не найден
. . . . . . . . . . . . ; Продолжение при наличии
. . . . . . . . . . . . ; нулевого элемента
NotFound: . . . . . . . . . . . . ; Продолжение при отсутствии
. . . . . . . . . . . . ; нулевого элемента
В данном примере команда модификации адреса INC расположена перед командой CMP, что вызывает его инкрементирование перед первым сравнением. Поэтому для получения достоверного адреса первого элемента начальный адрес массива Array загружен в регистр BX на единицу меньшим значением. Команда INC не может находиться за командой CMP, так как она изменяет флаг ZF, искажая результат сравнения, полученный CMP и требующийся для LOOPNZ.