Команды условного перехода осуществляют переход, который выполняется только в случае истинности некоторого условия. Истинность условия проверяется по значениям флагов. Поэтому обычно непосредственно перед командой условного перехода ставится команда сравнения, которая формирует значения флагов:
CMP <операнд1>, <операнд2>
Команда сравнения эквивалентна команде SUB за исключением того, что вычисленная разность никуда не заносится. Назначение команды CMP – установка и сброс флагов.
Что касается команд условного перехода, то их достаточно много, но все они записываются единообразно:
Jxx <метка>
Все команды условного перехода можно разделить на три группы.
В первую группу входят команды, которые обычно ставятся после команды сравнения. В их мнемокодах указывается тот результат сравнения, при котором надо делать переход.
Мнемокод | Название | Условие перехода после команды CMP op1, op2 | Значения флагов | Примечание |
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 |
Рассмотрим пример: даны две переменные x и y, в переменную z нужно записать максимальное из чисел x и y.
|
|
mov eax, x
cmp eax, y
jge/jae L; Используем JGE для знаковых чисел и JAE – для беззнаковых
mov eax, y
L: mov z, eax
Во вторую группу команд условного перехода входят те, которые обычно ставятся после команд, отличных от команды сравнения, и которые реагируют на то или иное значение какого-либо флага.
Мнемокод | Условие перехода | Мнемокод | Условие перехода |
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 |
Рассмотрим пример: пусть a, b и c – беззнаковые переменные размером 1 байт, требуется вычислить c = a * a + b, но если результат превосходит размер байта, передать управление на метку ERROR.
mov al, a
mul al
jc ERROR
add al, b
jc ERROR
mov c, al
И, наконец, в третью группу входят две команды условного перехода, проверяющие не флаги, а значение регистра ECX или CX:
JCXZ <метка>; Переход, если значение регистра CX равно 0
JECXZ <метка>; Переход, если значение регистра ECX равно 0
Однако эта команда выполняется достаточно долго. Выгоднее провести сравнение с нулём и использовать обычную команду условного перехода.
|
|
С помощью команд перехода можно реализовать любые разветвления и циклы.
; if (x > 0) S
cmp x, 0
jle L
...; S
L:
; if (x) S1 else S2
cmp x, 0
je L1
...; S1
jmp L2
L1: ...; S2
L2:
; if (a > 0 && b > 0) S
cmp a, 0
jle L
cmp b, 0
jle L
...; S
L:
; if (a > 0 || b > 0) S
cmp a, 0
jg L1
cmp b, 0
jle L2
L1: ...; S
L2:
; if (a > 0 || b > 0 && c > 0) S
cmp a, 0
jg L1
cmp b, 0
jle L2
cmp c, 0
jle L2
L1: ...; S
L2:
; while (x > 0) do S
L1: cmp x, 0
jle L2
...; S
jmp L1
L2:
; do S while (x > 0)
L: ...; S
cmp x, 0
jg L