Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Системное программирование.doc
Скачиваний:
178
Добавлен:
19.03.2015
Размер:
1.96 Mб
Скачать

5.5. Команды переходов

Машинные команды выполняются в порядке расположения их в памяти. Но естественный порядок нередко приходиться нарушать, чтобы следующей выполнялась не очередная команда программы, а иная. Такую возможность обеспечивают команды перехода. Переходы различают условныеибезусловные. Если переход делается при выполнении некоторого условия, такой переход называется условным, а если независимо от условий, то это безусловный переход. Флаги команды перехода не изменяют.

Команда безусловного переходаJMP выполняетбезусловный ближний(внутрисегментный) идальний(межсегментный) переход по указанному адресу (табл. 47). Ближние переходы осуществляются с применением относительной (с 8- или 16-разрядным отклонением) и косвенной адресации, дальние – с применением прямой и косвенной адресации.

Табл. 47. Команда JMP.

Код

Инструкция

Описание

EB cb

JMP rel8

Безусловный короткий переход.

E9 cw

JMP rel16

Безусловный ближний переход.

FF /4

JMP r/m16

Безусловный ближний косвенный переход.

EA cd

JMP ptr16:16

Безусловный дальний переход.

FF /5

JMP m16:16

Безусловный дальний косвенный переход.

Операнд указывает адрес перехода, т.е. адрес команды, которая должна быть выполнена следующей. Обычно указывается метка команды, на которую следует передать управление. Непосредственный операнд указывать нельзя. Пример прямого перехода:

JMP L ; следующей будет выполняться команда с меткой L

...

L:...

Регистр указателя команд IP хранит адрес команды, которая должна быть выполнена следующей. Поэтому переход по некоторому адресу означает запись данного адреса в регистр IP. Однако команда прямого перехода устроена так, что в ней указывается не этот адрес, а разность между ним и адресом команды перехода. Действие команды перехода заключается в прибавлении этой величины к текущему значению регистра IP.

Выгода от указывания не адреса перехода, а расстояния от команды перехода заключается в экономии памяти. Если в команде указывать сам адрес перехода, то на него придется всегда отводить слово. В большинстве случаев переходы делаются на команды, расположенные недалеко от команд перехода, поэтому разность между адресами двух команд, как правило, небольшая, и достаточно одного байта.

Существуют две команды прямого перехода. В первой команде относительный адрес перехода задается в виде байта (короткий переход), а в другой – в виде слова (длинный переход). В каждой из этих команд операнд рассматривается как целое со знаком, поэтому при сложении его с IP значение регистра может, как увеличиться, так и уменьшиться, т.е. возможен переход поссылке вперед, и переход поссылке назад.

Встречая команду перехода, ассемблер вычисляет разность между адресом метки и адресом команды перехода, и оценивает величину этой разности. Если она укладывается в байт, ассемблер формирует машинную команду короткого перехода (1 байт), иначе – формирует команду длинного перехода (2 байта). Однако сделать такой выбор ассемблер в состоянии, если метка была описана до команды перехода, т.е. имеет место переход по ссылке назад.

Если в команде перехода указана ссылка вперед, то ассемблер не сможет оценить величину разности. В результате ассемблер не определит, какой переход – короткий или длинный, а потому на всякий случай сформирует команду длинного перехода.

Такой способ трансляции переходов не всегда выгоден: если метка окажется близко расположенной, то будет потерян один байт. Для указания короткого перехода существует оператор SHORT, который ставится в команде перехода перед меткой. В этом случае ассемблер формирует машинную команду короткого перехода:

JMP L ; длинный переход

JMP SHORT L ; короткий переход

Если указан оператор SHORT, но переход оказался длинным, ассемблер зафиксирует ошибку. При указании оператора перед меткой, описанной ранее, ассемблер проигнорирует его.

Косвенный переходявляется разновидностью безусловного. Он используются, когда адрес перехода известен только во время исполнения. В этом случае в команде перехода указывается не адрес перехода, а место, где он находится. Адрес может находиться в регистре общего назначения или занимать слово памяти. Полученный адрес рассматривается как «настоящий», а не отсчитанный от команды перехода. Примеры косвенных переходов:

A DW L

JMPA;goto[A] =gotoL

MOV DX, A ; DX = L

JMP DX ; goto [DX] = goto L

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

Команда эквивалентна команде SUB op1, op2, т.е. сравнение выполняется путём вычитания значения второго операнда из значения первого операнда. Результат вычитания теряется, однако на его основании устанавливаются флаги. При выполнении операции над 16-разрядным первым операндом и 8-разрядным вторым (код операции 83) перед операцией производится расширение знака второго операнда.

Табл. 48. Команда CMP.

Код

Инструкция

Описание

38 /r

CMP r/m8, r8

Сравнение r/m8 и r8.

39 /r

CMP r/m16, r16

Сравнение r/m16 и r16.

3A /r

CMP r8, r/m8

Сравнение r8 и r/m8.

3B /r

CMP r16, r/m16

Сравнение r16 и r/m8.

3C ib

CMP AL, imm8

Сравнение AL и imm8.

3D iw

CMP AX, imm16

Сравнение AX и imm16.

80 /7 ib

CMP r/m8, imm8

Сравнение r/m8 и imm8.

81 /7 iw

CMP r/m16, imm16

Сравнение r/m16 и imm16.

83 /7 ib

CMP r/m16, imm8

Сравнение r/m16 и imm8.

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

Табл. 49. Команда Jxx.

Код

Инструкция

Описание

77 cb

JA rel8

Переход, если выше (CF=0 и ZF=0).

73 cb

JAE rel8

Переход, если выше или равно (CF=0).

72 cb

JB rel8

Переход, если ниже (CF=1).

76 cb

JBE rel8

Переход, если ниже или равно (CF=1 или ZF=1).

72 cb

JC rel8

Переход, если есть перенос (CF=1).

E3 cb

JCXZ rel8

Переход, если регистр CX содержит 0.

74 cb

JE rel8

Переход, если равно (ZF=1).

7F cb

JG rel8

Переход, если больше (ZF=0 и SF=OF).

7D cb

JGE rel8

Переход, если больше или равно (SF=OF).

7C cb

JL rel8

Переход, если меньше (SF≠OF).

7E cb

JLE rel8

Переход, если меньше или равно (ZF=1 или SF≠OF).

76 cb

JNA rel8

Переход, если не выше (CF=1 или ZF=1).

72 cb

JNAE rel8

Переход, если не выше или равно (CF=1).

73 cb

JNB rel8

Переход, если не ниже (CF=0).

77 cb

JNBE rel8

Переход, если не ниже или равно (CF=0 и ZF=0).

73 cb

JNC rel8

Переход, если переноса нет (CF=0).

75 cb

JNE rel8

Переход, если не равно (ZF=0).

7E cb

JNG rel8

Переход, если не больше (ZF=1 или SF≠OF).

7C cb

JNGE rel8

Переход, если не больше или равно (SF≠OF).

7D cb

JNL rel8

Переход, если не меньше (SF=OF).

7F cb

JNLE rel8

Переход, если не меньше или равно (ZF=0 и SF=OF).

71 cb

JNO rel8

Переход, если переполнения нет (OF=0).

7B cb

JNP rel8

Переход, если результат нечётный (PF=0).

79 cb

JNS rel8

Переход, если знака нет (SF=0).

75 cb

JNZ rel8

Переход, если не нуль (ZF=0).

70 cb

JO rel8

Переход, если есть переполнение (OF=1).

7A cb

JP rel8

Переход, если результат чётный (PF=1).

7A cb

JPE rel8

Переход, если результат чётный (PF=1).

7B cb

JPO rel8

Переход, если результат нечётный (PF=0).

78 cb

JS rel8

Переход, если есть знак (SF=1).

74 cb

JZ rel8

Переход, если нуль (ZF=1).

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

  • E - equal (равно);

  • N - not (не, отрицание);

  • Е - greater (больше) для чисел со знаком;

  • L - less (меньше) для чисел со знаком;

  • A - above (выше, больше) для чисел без знака;

  • В - below (ниже, меньше) для чисел без знака.

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

В командах, предназначенных для переходов по результатам сравнения чисел со знаком, анализируются флаги SF и OF, а в командах для беззнаковых сравнений – флаг CF. В любом случае равенство или неравенство чисел отражается состоянием флага ZF.

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

Табл. 50. Мнемокоды сравнения по команде CMP.

Мнемокод

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

после 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

Рассмотрим пример совместного применения команды сравнения CMP и условного перехода. Пусть необходимо разместить в памяти два числа в порядке возрастания. Для определенности допустим, что числа беззнаковые, размером слово, а смещения их адресов в сегменте данных расположены в регистрах SIи DI.

MOV AX, [SI] ; загрузить в AX первое число

CMP AX, [DI] ; сравнить числа

JBE L ; переход, если первое число меньше либо равно второму

XCHG AX, [DI] ; иначе поменять их местами

MOV [SI], AX ; записать число из AX в ячейку памяти

L:...

Вторая группа команд условного переходасостоит из команд, которые реагируют на значение определенного флага. В мнемокодах команд указывается первый символ проверяемого флага, если переход должен быть выполнен при значении 1 у флага, либо этот символ указывается с символом N (not), если переход требуется сделать при нулевом значении флага (табл. 51). Легко заметить, что следующие пары мнемокодов эквиваленты: JE и JZ, JNE и JNZ, JB и JC, JNB и JNC.

Табл. 51. Мнемокоды сравнения по регистру флагов.

Мнемокод

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

J(N)Z

ZF=1(0)

J(N)S

SF=1(0)

J(N)C

CF=1(0)

J(N)O

OF=1(0)

J(N)P

PF=1(0)

Третья группа команд условного переходасодержит всего одну команду, реагирующую на нулевое значение регистра СХ:

JCXZ <метка>

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

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

Инструкция JCXZ является единственной командой условного перехода, которая не проверяет состояние флага или группы флагов. Вместо этого она проверяет содержимое регистра CX.

Общая особенность команд условного переходазаключается в том, что команды используют относительную адресацию с 8-разрядным отклонением, что ограничивает длину перехода 127 байтами вперёд и 128 байтами назад относительно адреса команды, следующей за инструкцией перехода (примерно 30-40 команд; в среднем одна команда занимает 3-4 байта). Использовать в командах условного перехода оператор SHORT не имеет смысла, т.к. все переходы короткие.

Для выполнения длинных условных переходов (на расстояние более 127 байтов от команды перехода, а также межсегментных) следует использовать команду длинного безусловного перехода. Например, при длинной метке М оператор:

if AX = BX then goto M

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

if AX<>BX then goto L; { короткий переход }

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

L:...

Ассемблер транслирует ее в следующий код:

CMP АХ, ВХ

JNE L

JMP М

L:...

M:...

Дальние переходы.Все описанные переходы являются ближними. При выполнении ближнего перехода операнд команды содержит новое значение указателя команд IP (смещение следующей выполняемой команды в текущем сегменте кода). Однако в общем случае в программе может быть много команд, и в результате они не поместятся в один сегмент памяти (суммарный размер команд превосходит 64 Кб).

При выполнении дальнего (межсегментного) перехода адрес следующей команды занимает два слова памяти: в первом хранится смещение, во втором – адрес сегмента. Таким образом, команда дальнего перехода загружает регистровую пару CS:IP.

Рассмотрим следующие два сегмента:

C1 SEGMENT

ASSUME CS: C1

START: MOV AX, 0

...

JMP FAR PTR L

C1 ENDS

C2 SEGMENT

ASSUME CS: C2

L: INC BX

...

C2 ENDS

Переход из сегмента C1 на метку L сегмента C2 будет дальним. При таких переходах меняется значение регистра CS и регистра IP: регистр CS настраивается на начало сегмента с меткой CS:=C2, а в регистр IP записывается смещение метки внутри сегмента IP:=OFFSETL.

В системе команд предусмотрены команды, реализующие дальние переходы, причем все они являются только безусловными прямыми или косвенными. В языке ассемблера в этих командах указывается также мнемокод JMP, но с дополнительными операторами. Флаги команды дальнего перехода не меняют:

JMP FAR PTR <метка>

Оператор FAR указывает ассемблеру, что метка дальняя и находится в другом сегменте. По этой команде регистр CS устанавливается на начало того сегмента, в котором находится метка, а в регистр IP записывается смещение метки внутри данного сегмента:

S:=seg <метка:> ; IP:=offset <метка:>

При дальнем косвенном переходе в команде указывается адрес двойного слова, в котором находится адрес перехода в виде адресной пары seg:disp, записанной в обратном порядке: смещение disp должно быть записано по адресу m32, а номер сегмента seg - по адресу m32+2:

JMP m32

Следует заметить, что если X является ссылкой вперед, существуют разновидности команды безусловного перехода:

JMP X ; близкий прямой длинный

JMP SHORT X ; близкий прямой короткий

JMP FAR PTR X ; дальний прямой

JMP WORD PTR X ; близкий косвенный

JMP DWORD PTR X ; дальний косвенный

Такие уточнения требуются и для команды JMP, если указана косвенная ссылка, например JMP [BX]. По умолчанию ассемблер рассматривает подобного рода команду как близкий косвенный переход. Если X – ссылка назад, то вид перехода обязательно следует уточнять только при дальнем прямом переходе. Ассемблер, зная, что X – метка из другого сегмента команд, все равно не будет рассматривать команду JMP X как дальний переход.

Встречая любую метку, ассемблер автоматически приписывает ей тип NEAR (близкий). Операторы NEAR и FAR являются именами стандартных констант со значениями соответственно -1 (0FFFFh) и -2 (0FFFEh).