Организация условных переходов 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Организация условных переходов



Команда TEST выполняет операцию поразрядного логического умножения между двумя указанными операндами равного размера и, в зависимости от полученного результата, устанавливает флаги состояния процессора. В отличие от команды AND, значение операнда получателя данных не изменяется. В команде TEST используются аналогичные команде AND типы операндов. Обычно команда TEST применяется для анализа значения отдельных битов числа по маске. Команда TEST всегда сбрасывает флаги переполнения (OF) и переноса (CF). Кроме этого модифицирует значения флагов знака (SF), нуля(ZF) и чётности (PF) согласно значению результата выполнения операции логического умножения.

Например, определение состояния нулевого и третьего битов регистра AL можно произвести следующей командой: test al,00001001b.

Варианты операции test при разных значениях регистра al:

al = 00100101

маска = 00001001

результат = 00000001

В этом примере согласно маске проверялся нулевой и третий бит. Флаг нуля сброшен zf = 0, т.к. результат не равен нулю.

al = 00100101

маска = 10000010

результат = 00000000

В этом примере согласно маске проверялся первый и седьмой бит. Флаг нуля установлен zf = 1, т.к. результат равен нулю.

Команда CMP вычитает операнд-источник из операнда-получателя и, в зависимости от полученного результата, устанавливает флаги состояния процессора. При этом в отличие от команды SUB, значение операнда-получателя не изменяется: cmp получатель,источник.

Команда CMP изменяет состояние следующих флагов: переполнения (OF) и переноса (CF), знака (SF), нуля(ZF), вспомогательного переноса (AF) и чётности (PF). Они устанавливаются в зависимости от значения, которое было бы получено в результате применения команды SUB. Операнд-получатель и операнд-источник могут находиться в отношении больше (>), меньше (<) и равно (=) между собой. В зависимости от этих отношений флаги могут принимать значения, показанные в таблицах 1.3.1 и 1.3.2.

Таблица 1.3.1. Состояние флагов после сравнения беззнаковых операндов с помощью команды cmp

Отношение между операндами ZF CF
Получатель < Источник    
Получатель > Источник    
Получатель = Источник    

Команда CMP очень важна, поскольку она используется практически во всех основных условных логических конструкциях. Если после команды CMP поместить команду условного перехода, то полученная конструкция будет аналогична оператору IF языка высокого уровня. Команда условного перехода передаёт управление по указанной метке в случае, если установлен соответствующий флаг состояния процессора. Если же флаг сброшен, то выполняется следующая за ней команда. В таблице 1.3.3 указаны команды условного перехода по значению отдельных флагов регистра EFLAGS.

Таблица 1.3.2. Состояние флагов после сравнения операндов со знаком с помощью команды cmp

Отношение между операндами Состояние флагов
Получатель < Источник SF¹OF, ZF=0
Получатель > Источник SF=OF, ZF=0
Получатель = Источник ZF=1

Таблица 1.3.3. Команды, выполняющие условный переход в зависимости от значения флагов

Мнемо-ника Описание Флаги Мнемо-ника Описание Флаги
JZ Переход, если ноль ZF=1 JS Переход, если знак минус SF=1
JNZ Переход, если не ноль ZF=0 JNS Переход, если знак плюс SF=0
JC Переход, если перенос CF=1 JP Переход, если чётное число единичных бит PF=1
JNC Переход, если нет переноса CF=0 JNP Переход, если нечётное число единичных бит или все биты сброшены (нулевые) PF=0
JO Переход, если переполнение OF=1
JNO Переход, если нет переполнения OF=0 - - -

В таблице 1.3.4 приведены команды выполняющие условный переход в зависимости от равенства двух операндов, независимо от того являются они знаковыми или нет. Команды JZ и JE являются синонимами, также и команды JNZ и JNE являются синонимами.

В таблице 1.3.5 приведены команды условного перехода, использующиеся после команд сравнения беззнаковых операндов. Этот тип команд условного перехода используется в случае, если нужно сравнить два беззнаковых числа, такие как 7Fh и 80h, и при этом предполагается, что первое число (7Fh = +127) должно быть меньше второго (80h = +128), а не наоборот, как в случае операндов со знаком: 7Fh = +127 и 80h = -128. Обратите внимание, что команды JNA и JBE являются синонимами, также и команды JAE и JNB являются синонимами.

Таблица 1.3.4. Команды, выполняющие переход в зависимости от равенства операндов

Мнемоника Описание Флаги
JZ Переход, если результат ноль ZF=1
JNZ Переход, если результат не ноль ZF=0
JE Переход, если операнды равны ZF=1
JNE Переход, если операнды не равны ZF=0
JCXZ Переход, если регистр CX=0 -
JECXZ Переход, если регистр ECX=0 -

Таблица 1.3.5. Команды условного перехода, использующиеся после команд cmp сравнения беззнаковых операндов

Мнемо-ника Знак отношения Описание Флаги
JA > Переход, если выше (above) CF=0 и ZF=0
JNA £ Переход, если не выше CF=1 или ZF=1
JAE ³ Переход, если выше или равно CF=0 или ZF=1
JB < Переход, если ниже (below) CF=1 и ZF=0
JNB ³ Переход, если не ниже CF=0 или ZF=1
JBE £ Переход, если ниже или равно CF=1 или ZF=1

В таблице 1.3.6 приведены команды условного перехода, использующиеся после команд сравнения знаковых операндов. Этот тип команд условного перехода используется в случае, если сравниваемые операнды должны интерпретироваться как числа со знаком. Например, при сравнении чисел 7Fh и 80h результат будет зависеть от того, являются ли эти числа знаковыми или беззнаковыми. Обратите внимание, что команды JNG и JLE являются синонимами, также и команды JGE и JNL являются синонимами.

Таблица 1.3.6. Команды условного перехода, использующиеся после команд cmp сравнения операндов со знаком

Мнемо-ника Знак отношения Описание Флаги
JG > Переход, если больше (great) SF=0 и ZF=0
JNG £ Переход, если не больше SF¹OF или ZF=1
JGE ³ Переход, если больше или равно SF=0 или ZF=1
JL < Переход, если меньше (less) SF¹OF и ZF=0
JNL ³ Переход, если не меньше SF=0 или ZF=1
JLE £ Переход, если меньше или равно SF¹OF или ZF=1

Заметка. Чтобы не путать понятия больше и меньше (great и less), которые используются при сравнении операндов со знаком, при сравнении операндов без знака используются понятия выше и ниже (above и below).

Команда безусловного перехода JMP совершает переход на указанную метку: jmp METKA.

Организация условных переходов осуществляется в два этапа. Вначале сравниваются два числа командой cmp (или производится логико-арифме-тическая операция, изменяющая флаги), после этого производится переход на метку в зависимости от состояния проверяемых флагов – признаков операции. На рисунке 1.3.2 показана граф схема алгоритма условного перехода, содержащая одну ветку и её реализация на ассемблере. Переменные A и B расположены в регистрах ax и bx соответственно.

Для случая условного перехода, содержащего две ветви, реализация алгоритма на ассемблере представлена на рисунке 1.3.3.

На ассемблере можно использовать две команды условного перехода после одной команды сравнения. После сравнения переменной A с числом 3 можно легко организовать три варианта дальнейших действий, которые на ЯВУ записываются оператором множественного выбора или операторами условных переходов, например, так:

If A=3 then A:=A+1

If A>3 then A:=A+2

If A<3 then A:=A+3

На ассемблере указанный код можно реализовать в таком виде:

cmp ax,3

jz M

jg S

add ax,3

jmp V

M:

add ax,1

jmp V

S:

add ax,2

V:

Пример 1.3.4. При сравнении двух чисел 7Fh и 80h переходы по условию выше (ja IsAbove) и по условию больше (jg IsGreater) будут различными. В данной программе будет всегда выполняться переход только на метку IsGreater.

.code

start:

mov al,7Fh; 7Fh = +127

cmp al,80h; 80h = +128 или -128?

ja IsAbove; Нет перехода на метку IsAbove, т.к. +127 < +128

jg IsGreater; Есть переход на метку IsGreater, т.к. +127 > -128

IsAbove:

PrintText "+127 > +128"

jmp E

IsGreater:

PrintText "+127 > -128"

E:

ret

end start

Пример 1.3.5. Приведённая ниже программа является расширением примера 1.3.3. Она не только создаёт массив байтов X, увеличивающийся от 0 до 255, но одновременно с ним создаёт массив Y, содержащий только те байты, у которых крайние биты (нулевой и седьмой) установлены, т.е. равны единице.

.data?

X byte 256 DUP (?)

Y byte 256 DUP (?)

.code

start:

mov al,0; первый элемент массива в al

mov esi,0; индекс первого элемента массива X в esi

mov edi,0; индекс первого элемента массива Y в edi

mov ecx,LENGTHOF X; инициализация счётчика цикла

M:; метка начала цикла

mov X[esi],al; пересылка в массив X по смещению esi байта из al

mov bl,al; создание копии очередного байта массива X

and bl,10000001b; сброс всех внутренних битов

cmp bl,10000001b; крайние биты равны единице?

jnz V; если нет, то на метку V, иначе идём ниже

mov Y[edi],al; пересылка в массив Y по смещению edi байта из al

inc edi; получение индекса следующего элемента массива Y

V:

inc al; получение следующего элемента массива X

inc esi; получение индекса следующего элемента массива X

loop M; проверка окончания цикла

DbgDump offset X, 256; вывод массива X

PrintLine

DbgDump offset Y, 256; вывод массива Y

ret

end start

Заметка. Команда пересылки байта из al в массив X по смещению esi

mov X[esi],al

имеет альтернативный синтаксис:

mov [X+esi],al.

Эти две команды абсолютно идентичны. Обозначение элемента массива X с индексом esi в виде X[esi] более привычно для людей, знающих языки высокого уровня. Однако следует иметь в виду, что на самом деле адрес элемента массива X с индексом esi определяется в виде суммы адреса первого элемента массива, т.е. адреса X, и смещения esi искомого элемента массива, т.е. [X+esi].

Пример 1.3.6. Приведённая ниже программа осуществляет шифрование с помощью закрытого ключа, роль которого играет байт 9Ah. Алгоритм шифрования основан на уникальном свойстве команды XOR. Если какую-либо переменную сложить с помощью команды XOR с числом-ключом, то получится зашифрованное число. Если же это зашифрованное число с помощью команды XOR ещё раз сложить с тем же числом-ключом, то мы получим исходное значение переменной, т.е. расшифруем число.

Key = 9Ah

.data

X byte “assembler masm32v9”; исходная строка

Y byte LENGTHOF X DUP (?); инициализация зашифр-ной строки

Z byte LENGTHOF X DUP (?); инициализация расшифр-ной строки

.code

start:

DbgDump offset X, LENGTHOF X; вывод исходной строки X

mov esi,0; индекс первой буквы строки X в esi

mov ecx,LENGTHOF X; инициализация счётчика цикла

M:; метка начала цикла шифрования

mov al,X[esi]; копируем букву исходной строки в регистр al

xor al,Key; шифруем букву

mov Y[esi],al; пересылаем шифрованную букву в строку Y

inc esi; получаем индекс следующей буквы строки X

loop M; проверка окончания цикла

PrintLine

DbgDump offset Y, LENGTHOF X; вывод зашифрованной строки Y

mov esi,0; индекс первой буквы строки Y в esi

mov ecx,LENGTHOF Y; инициализация счётчика цикла

S:; метка начала цикла расшифрования

mov al,Y[esi]; копируем букву зашифр-ной строки в регистр al

xor al,Key; расшифровываем букву

mov Z[esi],al; пересылаем расшифрованную букву в строку Z

inc esi; получаем индекс следующей буквы строки Y

loop S; проверка окончания цикла

PrintLine

DbgDump offset Z, LENGTHOF Z; вывод расшифр-ной строки Z

ret

end start



Поделиться:


Последнее изменение этой страницы: 2016-06-29; просмотров: 533; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.216.94.152 (0.046 с.)