 |
нуля в данном примере будет установлен только в случае нажатия
клавиши A, и только в этом случае процессор 8086 перейдет к вы-
полнению инструкции с меткой AWasTyped, то есть инструкции PUSH.
Набор инструкций процессора 8086 предусматривает большое
разнообразие инструкций условных переходов, что позволяет вам
осуществлять переход почти по любому флагу или их комбинации.
Можно осуществлять условный переход по состоянию нуля, переноса,
по знаку, четности или флагу переполнения и по комбинации фла-
гов, показывающих результаты операций чисел со знаками.
Перечень инструкций условных переходов приводится в Таблице
5.2.
Инструкции условных переходов Таблица 5.2
-----------------------------------------------------------------
Название Значение Проверяемые флаги
-----------------------------------------------------------------
JB/JNAE Перейти, если меньше / перейти, если CF = 1
не больше или равно
JAE/JNB Перейти, если больше или равно / пе- CF = 0
рейти, если не меньше
JBE/JNA Перейти, если меньше или равно / пе- CF = 1 или ZF = 1
рейти, если не больше
JA/JNBE Перейти, если больше / перейти, если CF = 0 и ZF = 0
не меньше или равно
JE/JZ Перейти, если равно ZF = 1
JNE/JNZ Перейти, если не равно ZF = 0
JL/JNGE Перейти, если меньше чем / перейти, SF = OF
если не больше чем или равно
JGE/JNL Перейти, если больше чем или равно / SF = OF
перейти, если не меньше чем
JLE/JNLE Перейти, если меньше чем или равно / ZF = 1 или SF = OF
перейти, если не больше, чем
JG/JNLE Перейти, если больше чем / перейти, ZF = 0 или SF = OF
если не меньше чем или равно
JP/JPE Перейти по четности PF = 1
JNP/JPO Перейти по нечетности PF = 0
JS Перейти по знаку SF = 1
JNS Перейти, если знак не установлен SF = 0
JC Перейти при наличии переноса CF = 1
JNC Перейти при отсутствии переноса CF = 0
JO Перейти по переполнению OF = 1
JNO Перейти при отсутствии переполнения OF = 0
-----------------------------------------------------------------
CF - флаг переноса, SF - флаг знака, OF - флаг переполне-
ния, ZF - флаг нуля, PF - флаг четности
Более подробная информация об инструкциях-синонимах и общие
сведения об инструкциях перехода содержатся в Главе 6. Там также
подробно рассказывается о способах, с помощью которых инструкции
процессора 8086 могут изменять регистр флагов.
Несмотря на свою гибкость, инструкции условного перехода
имеют также серьезные ограничения, поскольку переходы в них всег-
да короткие. Другими словами целевая метка, указанная в инструк-
ции условного перехода, должна отстоять от инструкции перехода не
более, чем на 128 байт. Например, Турбо Ассемблер не может ас-
семблировать:
.
.
.
JumpTarget:
.
.
.
DB 1000 DUP (?)
.
.
.
dec ax
jnz JumpTarget
.
.
.
так как метка JumpTarget отстоит от инструкции JNZ более чем на
1000 байт. В данном случае нужно сделать следующее:
.
.
.
JumpTarget:
.
.
.
DB 1000 DUP (?)
.
.
.
dec ax
jnz SkipJump
jmp JumpTarget
SkipJump:
.
.
.
где условный переход переход применяется для того, чтобы опреде-
лить, нужно ли выполнить длинный безусловные переход.
Циклы
-----------------------------------------------------------------
Одним из видов конструкций в программе, которые можно пост-
роить с помощью условных переходов, являются циклы. Цикл - это
просто-напросто блок кода, завершающийся условным переходом, бла-
годаря чему данных блок может выполняться повторно до достижения
условия завершения. Возможно, вам уже знакомы такие конструкции
циклов, как for и while в языке Си, while и repeat в Паскале и
FOR в Бейсике.
Для чего используются циклы? Они служат для работы с масси-
вами, проверки состояния портов ввода-вывода до получения опреде-
ленного состояния, очистки блоков памяти, чтения строк с клавиа-
туры и вывода их на экран и т.д. Циклы - это основное средство,
которое используется для выполнения повторяющихся действий. Поэ-
тому используются они довольно часто, настолько часто, что в на-
боре инструкций процессора 8086 предусмотрено фактически несколь-
ко инструкций циклов: LOOP, LOOPNE, LOOPE и JCXZ.
Давайте рассмотрим сначала инструкцию LOOP. Предположим, мы
хотим вывести 17 символов текстовой строки TestString. Это можно
сделать следующим образом:
.
.
.
.DATA
TestString DB 'Это проверка! ...'
.
.
.
.CODE
.
.
.
mov cx,17
mov bx,OFFSET TestString
PrintStringLoop:
mov dl,[bx] ; получить следующий
; символ
inc bx ; ссылка на следующий
; символ
mov ah,2 ; функция DOS вывода на
; экран
int 21h ; вызвать DOS для вывода
; символа
dec cx ; уменьшить счетчик длины
; строки
jnz PrintStringLoop ; обработать следующий
; символ, если он имеется
.
.
.
Есть, однако, лучший способ. Возможно, вы помните, что ранее
мы уже упоминали о том, что регистр CX весьма полезно бывает ис-
пользовать для организации циклов. Инструкция:
loop PrintStringLoop
делает то же, что и инструкции:
dec cx
jnz PrintStringLoop
однако выполняется она быстрее и занимает на один байт меньше.
Всякий раз, когда вам нужно организовать цикл, пока значение
счетчика не станет равным 0, запишите начальное значение счетчика
в регистр CX и используйте инструкцию LOOP.
Как же строятся циклы с более сложным условием завершения,
чем обратный отсчет значения счетчика? Для таких случаев предус-
мотрены инструкции LOOPE и LOOPNE.
Инструкция LOOPE работает также, как инструкция LOOP, только
цикл при ее выполнении будет завершаться (то есть перестанут вы-
полняться переходы), если регистр CX примет значение 0 или флаг
|