Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 3000239.doc
Скачиваний:
23
Добавлен:
30.04.2022
Размер:
1.12 Mб
Скачать

4.2. Команды сравнения и условного перехода

Если переход осуществляется только при выполнении некоторого условия и не осуществляется в противном случае, то такой переход называется условным. Условный переход обычно реализуется в два шага: сначала сравниваются некоторые величины, в результате чего соответствующим образом формируются флаги (ZF, SF и т. д.), а затем выполняется собственно условный переход в зависимости от значений флагов. Поэтому мы сейчас рассмотрим и команду сравнения, и команды условного перехода.

Сравнение (compare): CMP op1, op2

Эта команда эквивалентна команде SUB op1, op2 за одним исключением: вычисленная разность op1-op2 никуда не записывается. Поэтому единственный и главный эффект от команды сравнения – это установка флагов, характеризующих полученную разность, или, что то же самое, характеризующих сравниваемые величины op1 и op2. Как формируются флаги при вычитании, уже ,было рассмотрено ранее, поэтому повторяться не будем.

Что же касается команд условного перехода, то их в ПК достаточно много, но в языке ассемблера они все записываются единообразно:

Jxx <метка>

где операнд указывает метку той команды программы, на которую надо сделать переход в случае выполнения некоторого условия, а мнемокод начинается буквой J (от jump), за которой следует одна или несколько букв, в сокращенном виде описывающих это условие.

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

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

Е – equal (равно)

N – not (не, отрицание)

G – greater (больше) для чисел со знаком

L – less (меньше)

А – above (выше, больше) для чисел без знака

В – below (ниже, меньше)

Как видно, для условий «меньше» и «больше» введены две системы обозначений. Это связано с тем, что после срав­нения чисел со знаком и сравнения чисел без знака надо реагировать на разные значения флагов.

Отметим, что одна и та же команда условного перехода может иметь в языке ассемблера несколько названий-синонимов. Это объясняется тем, что одно и то же условие перехода может быть сформулировано по-разному. Например, условие «меньше» – это в то же время и условие «не верно, что больше или равно», поэтому переход по меньше для знаковых чисел обозначается и как JL, и как JNGE. Какое из этих названий-синонимов использовать – это личное дело автора программы.

В табл. 8 приведены названия всех команд условного перехода, используемых после команды сравнения (через косую черту указаны названия-синонимы):

Таблица 8

Названия команд условного перехода, используемых

после команды сравнения

Мнемокод

Условие

Состояние флагов

для любых чисел

JE

op1 = op2

ZF = 1

JNE

op1 <> op2

ZF = 0

для чисел со знаком

JL / JNGE

op1 < op2

SF <> OF

JLE / JNG

op1 <= op2

SF <> OF или ZF = 1

JG / JNLE

op1 > op2

SF = OF и ZF = 0

JGE / JNL

op1 >= op2

SF = OF

для чисел без знака

JB / JNAE

op1 < op2

CF = 1

JBE / JNA

op1 <= op2

CF = 1 или ZF = 1

JA / JNBE

op1 > op2

CF = 0 и ZF = 0

JAE / JNB

op1 >= op2

CF = 0

Следует объяснить, к примеру, почему в команде условного перехода «по меньше» для знаковых чисел (JL) проверяется соотношение OF<>SF. Если в команде CMP op1,op2 сравниваемые числа трактуются как знаковые, тогда возможны две комбинации флагов, соответствующие условию op1<op2. Во-первых, если при «вычитании op1-op2 не было переполне­ния мантиссы (OF=0), тогда флаг SF фиксирует настоящий знак разности op1-op2 и потому SF=1 означает, что op1-op2<0, т. е. op1<op2. Во-вторых, если при вычитании произошло переполнение мантиссы (OF=1), тогда результатом команды будет число с противоположным знаком, чем у настоящей разности, и поскольку флаг SF фиксирует не знак настоящей разности, а знак результата команды, то условие SF=0 означает, что у искаженного результата знак положителен, а значит, у настоящей разности знак отрицателен, т. е. op1<op2. Итак, условию op1<op2 соответствует либо OF=0 и SF=1, либо OF=1 и SF=0, что можно записать более коротко: OF<>SF. Именно это условие и указано в таблице для команды JL.

Пример. Пусть X, Y и Z – переменные размером в слово. Требуется записать в Z максимальное из чисел X и Y.

Решение этой задачи различно для чисел со знаком (см. слева) и для чисел без знака (см. справа), т. к. приходится использовать разные команды условного перехода:

; числа со знаком

MOV АХ, Х

CMP AX, Y ;x=y?

JGE М ;х>=У -> М

MOV AX, Y

М: MOV Z, AX

;числа без знака

MOV АХ, Х

CMP AX, Y

JAE М

MOV AX, Y

M: MOV Z, AX

Во вторую группу команд условного перехода входят те, которые ставятся после команд, отличных от команды сравнения, и которые реагируют на то или иное значение какого-нибудь определенного флага. В мнемокодах этих команд указывается первая буква проверяемого флага, если переход должен быть выполнен при значении 1 у флага, либо эта буква указывается с буквой N (not), если переход надо сделать при нулевом значении флага. Обозначения команд приведены в табл. 9.

Таблица 9

Названия команд условного перехода по значению

определенного флага

Мнемокод

Условие

перехода

Мнемокод

Условие перехода

JZ

ZF=1

JNZ

ZF=0

JS

SF=1

JNS

SF=0

JC

CF=1

JNC

CF=0

JO

OF=1

JNO

OF=0

JP

PF=1

JNP

PF=0

Замечание. Легко заменить, что следующие пары мнемокодов эквивалентны: JE и JZ, JNE и JNZ, JB и JC, JNB и JNC.

Пример. Пусть А, В и С – беззнаковые байтовые переменные. Требуется вычислить С=А*А+В, но если ответ превосходит размер байта, тогда надо передать управление на метку ERROR.

Возможное решение это задачи:

MOV AL, A

MUL AL

JC ERROR ;A*A > 255 (CF=1) --> ERROR

ADD AL, B

JC ERROR ;перенос (CF=1) --> ERROR

MOV C, AL

И, наконец, в третью группу входит только одна команда условного перехода, проверяющая не флаги, а значение регистра CX:

JCXZ <метка>

Действие команды JCXZ (jump if CX is zero) можно описать так:

if CX=0 then goto <метка>

Примеры на использование этой команды будут приведены позже.

Отметим общую особенность команд условного перехода: все они осуществляют только короткий переход, т. е. с их помощью можно передать управление не далее чем на 127-128 байтов вперед или назад. Это примерно 30-40 команд (в среднем одна команда ПК занимает 3-4 байта). Дело в том, что в ПК все машинные команды условного перехода имеют вид КОПi8 и реализуют короткий относительный переход: IP:=IP+i8, а команд с операндом в слово (i16) нет. Это объясняется тем, что в большинстве случаев как раз и нужны такие короткие переходы, а с другой стороны, для команд длинных условных переходов в ПК попросту не хватило кодов операций.

Естественно, возникает вопрос: а как в этих условиях осуществлять длинные условные переходы, на расстояние более 127 байтов от команды перехода? Здесь надо привлекать команду длинного безусловного перехода. Например, при «далекой» метке М оператор

if AX=BX then goto M

следует реализовывать так:

if AXOBX then goto L ;{короткий переход}

goto M ;{длинный переход}

L: …

На языке ассемблера это записывается следующим образом:

СМР АХ,ВХ

JNE L

JMP М

L: …

Получается очень коряво, то иного варианта нет.

Отметим, что использовать в командах условного перехода оператор SHORT не надо, т. к. все эти переходы и так короткие.