Команды передачи управления

Команды передачи управления

CALL – Вызов подпрограммы

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

Команда call имеет четыре модификации:

· вызов прямой ближний (в пределах текущего программного сегмента);

· вызов прямой дальний (вызов подпрограммы, расположенной в другом программном сегменте);

· вызов косвенный ближний;

· вызов косвенный дальний.

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

near ptr – прямой ближний вызов;

far ptr – прямой дальний вызов;

word ptr – косвенный ближний вызов;

dword ptr – косвенный дальний вызов.

Команда call прямого ближнего вызова заносит в стек относительный адрес точки возврата в текущем программном сегменте и модифицирует IP так, чтобы в нем содержатся относительный адрес точки перехода в том же программном сегменте. Необходимая для вычисления этого адреса величина смещения от точки возврата до точки перехода содержится в коде команды, который занимает 3 байт (код операции E8h и смещение к точке перехода).

Команда call прямого дальнего вызова заносит в стек два слова – сначала сегментный адрес текущего программного сегмента, а затем (выше, в слово с меньшим адресом) относительный адрес точки возврата в текущем программном сегменте. Далее модифицируются регистры IP и CS: в IP помещается относительный адрес точки перехода в том сегменте, куда осуществляется переход, а в CS – сегментный адрес этого сегмента. Обе эти величины берутся из кода команды, который занимает 5 байт (код операции 9Аh, относительный адрес вызываемой подпрограммы и ее сегментный адрес).

Косвенные вызовы отличаются тем, что адрес перехода извлекается не из кода команды, а из ячеек памяти; в коде команды содержится информация о том, где находится адрес вызова. Длина кода команды зависит от используемого способа адресации.

RET –Возврат из процедуры

RETN –Возврат из ближней процедуры

RETF –Возврат из дальней процедуры

Команда ret извлекает из стека адрес возврата и передает управление назад в программу, первоначально вызвавшую процедуру. Если командой ret завершается ближняя процедура, объявленная с атрибутом near, или используется модификация команды retn, со стека снимается одно слово– относительный адрес точки возврата. Передача управления в этом случае осуществляется в пределах одного программного сегмента. Если командой ret завершается дальняя процедура, объявленная с атрибутом far, или используется модификация команды retf, со стека снимаются два слова: смещение и сегментный адрес точки возврата. В этом случае передача управления может быть межсегментной.

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

Jcc –Команды условных переходов

Команды, обозначаемые (в книгах, не в программах!) Jcc, осуществляют переход по указанному адресу при выполнении условия, заданного мнемоникой команды. Если заданное условие не выполняется, переход не осуществляется, а выполняется команда, следующая за командой Jcc. Переход может осуществляться как вперед, так и назад в диапазоне +127. -128 байт.

В составе команд процессора предусмотрены следующие команды условных переходов:

Таблица 25 – Условия перехода

Команда Условие перехода
ja выше CF=0 и ZF=0
jae выше или равно CF=0
jb ниже CF=1
jbe ниже или равно CF=1 или ZF=1
jc перенос CF=1
jcxz CX=0
je равно ZF=1
jg больше ZF=0 или SF=OF
jge больше или равно SF=OF
jl меньше SF не равно OF
jle меньше или равно ZF=1 или SF не равно OF
jna не выше CF=1 или ZF=1
jnae не выше и не равно CF=1
jnb не ниже CF=0
jnbe не ниже и не равно CF=0 и ZF=0
jnc нет переноса CF=0
jne не равно ZF=0
jng не больше ZF=1 или SF не равно OF
jnge не больше и не равно SF не равно OF
jnl не меньше SF=OF
jnle не меньше и не равно ZF=0 и SF=OF
jno нет переполнения OF=0
jnp нет четности PF=0
jns знаковый бит равен О SF=0
jnz не нуль ZF=0
jo переполнение OF=1
jp есть четность PF=1
jpe сумма битов четная PF=1
jpo сумма битов нечетная PF=0
js знаковый бит равен SF=1
jz нуль ZF= I

Команды условных переходов, осуществляющие переход по условию «выше – ниже», предназначены для анализа чисел без знака; команды, осуществляющие переход по условию «больше – меньше», предназначены для анализа чисел со знаком.

JMP –Безусловный переход

Команда jmp передает управление в указанную точку того же или другого программного сегмента. Адрес возврата не сохраняется. Команда не воздействует на флаги процессора.

Команда jmp имеет пять разновидностей:

– переход прямой короткий (в пределах -128. + 127 байтов);

– переход прямой ближний (в пределах текущего программного сегмента) ;

– переход прямой дальний (в другой программный сегмент);

– переход косвенный ближний;

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

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

short – прямой короткий переход;

near ptr – прямой ближний переход;

far ptr – прямой дальний переход;

word ptr – косвенный ближний переход;

dword ptr – косвенный дальний переход.

INT –Программное прерывание

Команда int инициирует в процессоре процедуру прерывания, в результате которой управление передается на обработчик прерывания с номером, который указан в качестве операнда команды int. В стек текущей программы заносится содержимое регистра флагов, сегментного регистра CS и указателя команд IP, после чего в регистры IP и CS передается содержимое двух слов из вектора прерывания с номером n (расположенных по адресам 0:n*4 и 0:n*4+2). Команда сбрасывает флаги IF и TF в 0. Команда iret, которой всегда завершается обработчик прерывания, восстанавливает исходное состояние этих флагов.

INTO –Прерывание по переполнению

Команда into, будучи установлена вслед за какой-либо арифметической, логической или строковой командой, вызывает обработчик прерываний через вектор 4, если предшествующая команда установила флаг переполнения OF. Перед использованием команды INTO прикладной программист должен поместить в вектор прерывания 4 двухсловный адрес своей программы обработки прерывания по переполнению. Команда сбрасывает флаги IF и TF в 0. Команда iret, которой всегда завершается обработчик прерывания, восстанавливает исходное состояние этих флагов.

IRET –Возврат из прерывания

Команда iret возвращает управление прерванному в результате аппаратного или программного прерывания процессу. Команда извлекает из стека три верхние слова и помещает их в регистры IP, CS и флагов (см. команду int). Командой iret должен завершаться любой обработчик прерываний, как аппаратных, так и программных (от команды int). Команда не воздействует на флаги, однако она загружает в регистр флагов из стека его исходное содержимое, которое было там сохранено процессором в процессе обслуживания прерывания. Если требуется, чтобы после возврата из обработчика программного прерывания командой iret какие-либо флаги процессора были установлены требуемым образом (весьма распространенный прием), их установку надо выполнить в копии флагов в стеке.

Команды передачи управления

Дата добавления: 2015-06-12 ; просмотров: 5964 ; Нарушение авторских прав

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

Команды безусловных переходов. Включают три мнемокода: JMP (безусловный переход), CALL (вызов подпрограммы) и RET (возврат из подпрограммы).

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

Первый формат обеспечивает переход в произвольную точку программы внутри текущего программного сегмента, для чего к содержимому IP добавляется в дополнительном коде 16-разряд­ное смещение, старший разряд которого является знаковым. Вто­рой, укороченный формат позволяет перейти к точке программы, отстоящей не более чем на -128-f-127 адресов от команды JMP. Наконец, третий формат осуществляет загрузку указателя команд 16-разрядным числом, которое размещено по исполни­тельному адресу ЕА, определяемому постбайтом. Этот переход называется косвенным, так как используется косвенная адреса­ция.

Для реализации безусловного перехода к точке программы, расположенной вне текущего программного сегмента, когда тре­буется перезагрузка сегментного регистра CS, используются четвертый и пятый форматы команды JMP.

Четвертый формат определяет прямой межсегментный пере­ход, при котором во втором и третьем байтах формата указан относительный адрес точки перехода, а в четвертом и пятом бай­тах- новое значение CS. Пятый формат с помощью постбайта позволяет определить исполнительный адрес ЕА, по которому на­ходится относительный адрес точки перехода (в байтах памяти с адресами ЕА, ЕА+1), и новое значение CS (в байтах памяти ЕА+2, ЕА+3).

Команда CALL позволяет вызвать подпрограмму, располо­женную как в текущем программном сегменте, так и в другой области памяти. Она имеет такие же форматы, что и команда JMP, за исключением укороченного. В отличие от команды JMP аналогичного формата по команде CALL перед изменением зна­чений IP или IP и CS происходит автоматическая запись в стек текущих значений этих регистров, что обеспечивает запомина­ние точки возврата из подпрограммы.

Для возврата из подпрограммы используется команда RET, под действием которой происходит передача управления по ад­ресу возврата, занесенному в стек при выполнении предыдущей команды CALL. При возврате из подпрограмм, расположенных в текущем программном сегменте, применяются первые два фор­мата команды RET, причем второй формат отличается от перво­го тем, что к содержимому указателя стека добавляется констан­та, записанная во 2-м и 3-м байтах команды. Это позволяет одновременно с возвратом из подпрограммы сбрасывать пара­метры, записанные в стек при выполнении этой подпрограммы и не используемые в дальнейшем.

Для межсегментного возврата применяются третий и четвер­тый форматы RET, которые обеспечивают восстановление содер­жимого как указателя команд, так и программного сегмента.

Команды условных переходов.Осуществляют передачу уп­равления в зависимости от результатов предыдущих операций. Различают три разновидности условных переходов, которые ис­пользуются для установления соотношений чисел со знаком, чи­сел без знака и произвольных чисел. В первых двух разновидно­стях для одних и тех же соотношений между числами выбирают­ся различные мнемокоды команд, поскольку одним и тем же соотношениям чисел со знаком и чисел без знака соответствуют различные значения флагов.

В мнемокодах команд условных переходов при сравнении чи­сел со знаком для обозначения условия «больше» используется буква G (Greater — больше), а для обозначения — «меньше» буква L (Less — меньше). Для аналогичных условий при сравне­нии чисел без знака используются соответственно буквы A (Abo­ve— над) и В (Below — под). Условие равенства обозначается буквой Е (Equal — равно), а невыполнение некоторого условия — буквой N (Not — не). Следует отметить, что допускается исползование двух различных мнемокодов для каждой команды; на­пример, мнемокоды JL и JNGF — эквивалентны, поскольку ус­ловия «меньше» и «не больше или равно» — идентичны.

Полный список мнемокодов команд, проверяемых условий, а также соответствующие булевские комбинации флагов и их зна­чения приведен в табл. 1.4.

Мнемокод команды Условие Значение флагов
Для чисел со знаком
JL/JNGE Меньше/не больше или равно SF + OF = l
JNL/JGE Не меньше/больше или равно SF + OF = 0
JG/JNLE Больше/не меньше или равно (SF + OF) V ZF = 0
JNG/JLE Не больше/меньше или равно Для чисел без знака (SF + OF) V ZF = l
JB/JNAE Меньше/не больше или равно CF = 1
JNB/JAE Не меньше/больше или равно CF = 0
JA/JNBE Больше CF V ZF = 0
JNA/JBE Не больше Для прочих данных CF V ZF = 1
JE/JZ Равно/по нулю ZF = 1
JNE/JNZ Не равно/по нулю ZF = 0
JS По минусу SF = 1
JNS По плюсу SF = 0
JO По переполнению OF = l
JNO По отсутствию переполнения OF = 0
JP/JPE По четному паритету PF = 1
JNP/JPO По нечетному паритету PF = 0

Все команды условных переходов имеют одинаковый двух­байтовый формат, в первом байте которого задается код опера­ции (КОП), а во втором — 8-разрядное смещение, которое рас­сматривается как число со знаком и, следовательно, позволяет осуществлять изменение адреса в диапазоне от -128 до +127. При необходимости более отдаленного («дальнего») перехода по выполнению условия используется дополнительно команда безусловного перехода.

Время выполнения каждой из команд условных переходов указано для двух случаев: 1) условие выполнено и управление действительно передается в соответствии со смещением, 2) ус­ловие не выполнено, так что управление передается следующей команде.

Команды организации циклов.Введены в ЦП для удобства выполнения вычислительных циклов. К ним относятся следующие мнемокоды: LOOP (цикл, пока (СХ) не равно 0), LOOPNZ/LOOPNE (цикл, пока не нуль/не равно), LOOPZ/LOOPE (цикл, пока нуль/равно) и JCXZ (переход по нулю в СХ). Каждая из этих команд имеет двухбайтовый формат, во втором байте кото­рого указывается 8-разрядное смещение, используемое для орга­низации перехода. Это смещение рассматривается как число со знаком и перед вычислением адреса перехода оно расширяется со знаком до 16 разрядов.

Читайте также  Охранно-пожарная сигнализация своими руками

Используя команды циклов совместно с командами манипу­ляции элементами строк, можно составлять достаточно сложные программы преобразования строк. Рассмотрим пример составле­ния программы для перевода строки данных, записанных в шестнадцатеричной системе счисления, в некоторый код, для которого перекодировочная таблица находится в памяти с начального ад­реса, указанного в ВХ, как это требуется для использования команды табличного преобразования кодов XLAT. Пусть далее исходная строка содержит 80 элементов и находится в памяти с относительного начального адреса 100, а строка-результат дол­жна быть размещена с относительного адреса 200. Программа, выполняющая перекодировку исходной строки в строку-резуль­тат, при значении флага направления DF=0 будет иметь вид:

MOV SI ,100
MOV DI ,200
MOV СХ , 80

Здесь использована команда табличного преобразования кодов XLAT, описанная в 1.2.

Команды прерывания.Включают три мнемокода: INT (пре­рывание), INTO (прерывание при переполнении) и IRET (воз­врат из прерывания).

Команда прерывания INT при v = 1 имеет двухбайтовый фор­мат, второй байт которого содержит 8-разрядное число, определя­ющее тип (type) или уровень прерывания. По команде INT type процессор переходит к выполнению программы обслуживания прерывания указанного уровня, причем автоматически выполня­ются действия, необходимые для обеспечения возврата в точку прерывания. Эти действия состоят в следующем: содержимое регистра флагов F записывается в стек (PUSHF), сбрасывают­ся флаги IF и TF, текущие значения регистра CS и указателя команд IP записываются в стек.

Для определения начального адреса программы обслужива­ния в соответствии со значением type используется таблица уровней прерывания. Для каждого из 256 уровней прерываний в этой таблице от­ведено по четыре байта: первые два байта определяют значение указателя команд IP, вторые — значение сегментного регистра CS. Эта четверка байтов определяет начальные адреса программ обслуживания (пары значений CS, IP), которые должны быть предварительно записаны в ячейки памяти по абсолютным адре­сам 0-3FFH. Адрес таблицы, соответствующий указанному в команде INT type уровню прерывания, определяется в ЦП сле­дующим образом. После запоминания в стеке текущих значений CS и ГР осуществляются загрузки: CS = type x 4 + 2 и IP = type x 4. Новые значения CS и IP, взятые соответственно из ячеек с адресами type x 4 + 2 и type x 4, определяют начальный адрес требуемой программы обслуживания.

Рассмотренная выше команда прерывания INT при значении поля v = 0 имеет однобайтовый формат, т. е. не требует специаль­ного указания уровня прерывания. Эта команда автоматически воспринимается процессором как прерывание третьего уровня (type=3) и обычно используется в программах в качестве контрольной точки.

Команда прерывания при переполнении INTO вызывает пе­реход на обслуживание прерывания четвертого уровня (type = 4) в случае, когда значение флага переполнения OF = 1. Команда INTO обычно используется после арифметических команд над числами со знаком. Обычно несколько первых уровней прерыва­ний (до 32) резервируются под обработку ряда специфических ситуаций, таких, например, как попытка деления на нуль, переполнение и тому подобных.

Особенность обработки прерываний зарезервированных уров­ней состоит в том, что процессор переходит к их обслуживанию независимо от значения флага IF разрешения прерываний.

Однобайтовая команда IRET ставится в конце каждой про­граммы обслуживания прерывания и обеспечивает возврат из прерывания. По этой команде процессор извлекает из стека значение указателя команд IP и программного сегмента CS, а также восстанавливает прежнее содержимое регистра флагов F (как и по команде POPF). При необходимости содержимое остальных регистров ЦП, соответствующее прерываемой программе, может быть запомнено в стеке при переходе на программу обслужива­ния и затем восстановлено при возврате из нее с помощью команд обращения к стеку.

Команды передачи управления

Табл 3. Команды передачи управления:

Команда

Описание

Действие

Циклы

Код операции

Флаги

ATtiny

ATmega

1100 kkkk kkkk kkkk

Indirect Jump to (Z)

1001 0100 0000 1001

Extended Indirect
Jump to (Z)

1001 0100 0001 1001

1001 010k kkkk 110k
kkkk kkkk kkkk kkkk

Relative Subroutine Call

STACK←PC+1,
PC←PC+k+1,
SP←SP-2 or 3

1101 kkkk kkkk kkkk

Indirect Call to (Z)

STACK←PC+1, PC←(Z),
SP←SP-2 or 3

1001 0101 0000 1001

Extended Indirect
Call to (Z)

1001 0101 0001 1001

Direct Subroutine Call

STACK←PC+1, PC←k,
SP←SP-2 or 3

1001 010k kkkk 111k
kkkk kkkk kkkk kkkk

PC←STACK,
SP←SP+2 or 3

1001 0101 0000 1000

PC←STACK,
SP←SP+2 or 3

1001 0101 0001 1000

Compare, Skip if Equal

if(Rd=Rr)
PC←PC+2 or 3

0001 00rd dddd rrrr

0001 01rd dddd rrrr

Compare with Carry

0000 01rd dddd rrrr

Compare Register with Immediate

0011 KKKK dddd KKKK

Skip if Bit in
Register is Cleared

if(Rr(b)=0)
PC←PC+2 or 3

1111 110r rrrr obbb

Skip if Bit in
Register is Set

if(Rr(b)=1)
PC←PC+2 or 3

1111 111r rrrr obbb

Skip if Bit in IO
Register is Cleared

if(P(b)=0)
PC←PC+2 or 3

1001 1001 PPPP Pbbb

Skip if Bit in IO
Register is Set

if(P(b)=1)
PC←PC+2 or 3

1001 1011 PPPP Pbbb

Branch if Status
Flag is Cleared

1111 01kk kkkk ksss

Branch if Status
Flag is Set

1111 00kk kkkk ksss

Branch if Carry
Flag is Clearsd

1111 01kk kkkk k000

Branch if Carry
Flag is Set

1111 00kk kkkk k000

Branch if Same
or Higher

1111 01kk kkkk k000

Branch if Lower

1111 00kk kkkk k000

Branch if Not Equal

1111 01kk kkkk k001

Branch if Equal

1111 00kk kkkk k001

1111 01kk kkkk k010

Branch if Minus

1111 00kk kkkk k010

Bruach if Overflow
Flag is Cleared

1111 01kk kkkk k011

Branch if Overflow
Flag is Set

1111 00kk kkkk k011

Branch if Greate or
Equal, Signed

1111 01kk kkkk k100

Branch if Less than
Zero, Signed

1111 00kk kkkk k100

Branch if Half Carry
Flag is Cleared

1111 01kk kkkk k101

Branch if Half Carry
Flag is Set

1111 00kk kkkk k101

Branch if Transfer
Flag is Cleared

1111 01kk kkkk k110

Branch if Transfer
Flag is Set

1111 00kk kkkk k110

Branch if Interrupt
Disable

1111 01kk kkkk k111

Branch if Interrupt
Enable

1111 00kk kkkk k111

Все команды группы передачи управления приведены в табл.3. Микроконтроллеры AVR могут содержать до 4-х разновидностей команды безусловного перехода. Команды такого типа модифицируют
содержимое программного счётчика, после чего программа продолжает выполняться с нового места (адреса перехода). Безусловный переход в памяти программ происходит не зависимо от каких либо условий, флагов программы и т.д.

Инструкция rjmp k (Относительный безусловный переход) позволяет осуществить переход в диапазоне +2047…-2047 слов в памяти программ от места где она расположена. Адрес перехода при этом зависит от текущего значения программного счётчика и вычисляется как смещение PC+1+k.

Команда ijmp (Косвенный безусловный переход) производит переход в памяти программ в пределах 0…65535 слов по адресу, находящемуся в индексном регистре Z. В этом случае адрес перехода является переменной величиной доступной из программы. Это даёт возможность легко реализовать процедуру ветвления, когда в зависимости от условий должен быть выполнен тот или иной фрагмент кода.

В моделях с объёмом памяти программ 256 кб доступна также команда eijmp (Расширенный безусловный косвенный переход). Она использует 3-байтовый указатель адреса EIND:ZH:ZL. В регистре EIND из пространства РВВ находится 17-тый бит адреса, а переход осуществляется в пределах 0…131071 слов.

Команда jmp k (Абсолютный безусловный переход) — переход по адресу k в любую точку из любого места программы. Абсолютный адрес перехода находится в коде операции, а команда занимает 2 слова (4 байта) и выполняется в течении 3-х машинных циклов.

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

Другим типом команд являются вызовы подпрограмм. Существуют следующие их разновидности: rcall k (Относительный вызов подпрограммы), icall (Косвенный вызов подпрограммы), eicall (Расширенный косвенный вызов подпрограммы) и call k (Абсолютный вызов подпрограммы). Функционируют такие инструкции аналогично командам безусловного перехода, но с одним существенным отличием. Перед переходом в памяти программ, адрес следующей команды предварительно сохраняется в специально отведённой для этих целей области памяти (стеке). Таким образом, находясь в любой точке программы, сохраняется возможность вернутся в то место, из которого был осуществлен вызов. Это действие осуществляет команда ret (Возврат из подпрограммы). Она загружает в PC сохранённый в стеке адрес возврата, после чего программа продолжает выполняться со следующей команды после rcall k, icall, eicall, call k:

В приведенном примере подпрограмма func1 может вызываться много раз из различных мест программы. Кроме того, в теле самой подпрограммы func1 могут содержаться вызовы различных подпрограмм (вызов func2 и т.д.). Такая организация программы позволяет максимально эффективно использовать ресурсы процессора, делает код более наглядным и позволяет многократно использовать разработанные подпрограммы в дальнейших проектах.

Еще одним скрытым механизмом вызова подпрограмм являются аппаратные прерывания. При их возникновении происходит вызов подпрограммы (обработчика прерывания) по фиксированному адресу (вектору прерывания), при этом адрес возврата также запоминается в стеке. Но в отличии от вызова по командам rcall k, icall, eicall, call k ещё и автоматически сбрасывается флаг глобального разрешения прерываний I в регистре SREG, т.е. запрещаются прерывания во время прерывания. Для выхода из прерывания используется команда reti (Возврат из прерывания) которая, загружает в PC адрес возврата и восстанавливает флаг I (разрешает прерывания при выходе из прерывания):

Иногда командой reti удобно завершить и обычную подпрограмму. Так бывает, когда, например, при выходе необходимо разрешить прерывания. В этом случае она фактически заменяет собой две инструкции sei (Разрешение прерываний) и ret:

Время выполнения rcall k, icall, call k, ret, reti зависит от величины программного счётчика конкретной модели. Если его разрядность более 16 бит (≥ 128 кб FLASH памяти), то для сохранения 3-байтового адреса возврата требуется на один машинный цикл больше.

В данную группу команд включены также 4 инструкции сравнения: cp Rd,Rr (Сравнить регистры), cpс Rd,Rr (Сравнить регистры с учётом переноса), cpi Rd,K (Сравнить регистр c константой), cpse Rd,Rr (Сравнить регистры и пропустить команду если они равны). Строго говоря первые три из них не являются командами передачи управления, так как не могут оказать влияние на счётчик программ. Единственным их предназначением является сравнение числовых величин, находящихся в РОН. Как видно из описания, команда cp Rd,Rr аналогична sub Rd,Rr, вместо cpc Rd,Rr фактически выполняется sbc Rd,Rr, а вместо cpi Rd,K — cubi Rd,K. Разница заключается только лишь в том, что содержимое регистра Rd остаётся неизменным. При этом переопределяется значение флагов Z,C,S, N,V,H регистра SREG по которым и можно судить о соотношении между числовыми величинами. В частности, сравнение двухбайтовых чисел находящихся в регистровых парах R19:R18 R17:R16 можно выполнить следующим образом:

В этом примере флага C окажется установленным, когда R19:R18 R17:R16). Что касается флага Z, то в данном случае он не может быть критерием проверки на нуль (Z=1 будет свидетельствовать только о равенстве R19=R17+C).

Стоит заметить также, что, подобно всем остальным командам, использующим непосредственную адресацию, cpi Rd,K может работать только с регистрами R16…R31.

Инструкция cpse Rd,Rr выполняется иначе. Она относится к типу Test and Skip (Проверка и пропуск). По логике работы команды такого рода выполняют проверку определённого условия и если оно истинно (в данном случае если Rd=Rr), то следующая в тексте команда пропускается. При этом все флаги программы остаются неизменными.

Помимо этого существуют ещё 4 команды Test and Skip ориентированных на проверку состояния определённого бита в регистрах. Две из них работают с РОН: sbrc Rr,b (Пропуск команды, если бит регистра сброшен), sbrs Rr,b (Пропуск команды, если бит регистра установлен). Ещё две с РВВ: sbic P,b (Пропуск команды, если бит регистра ввода-вывода сброшен), sbis P,b (Пропуск команды, если бит регистра ввода-вывода установлен). Если бит b(0…7) установлен при выполнении команд sbrs Rr,b и sbis P,b или сброшен для sbrc Rr,b, sbic P,b, то производится пропуск следующей команды. Нижеприведённый код демонстрирует программную задержку до тех пор пока не будет нажата кнопка подключённая к линии 1 порта B (пока бит 1 РВВ PINB не будет сброшен):

В отличии от команд sbrs Rr,b, sbrc Rr,b, которые работают со всеми без исключения РОН, инструкции sbis P,b, sbic P,b могут использовать только первые 32 РВВ. Если учесть, что число управляющих РВВ на много больше то, это довольно существенное ограничение. Конечно те РВВ, доступ к битам которых наиболее важен, разработчики постарались разместить именно в этой области. К ним относятся все регистры управления портами A,B,C,D,E,F, а также ряд других, отвечающих за работу EEPROM, USART, SPI т.д. Во всех остальных случаях необходимо cкопировать содержимое РВВ в один из РОН и уже дальше анализировать состояние соответствующего бита. Программное ожидание сброса бита 2 порта J должно выглядеть следующим образом:

Время выполнения инструкций Test and Skip может быть различным в зависимости от того пропускается следующая команда или нет. В первом случае необходимо 2 машинных цикла, во втором 1. Если же производится пропуск “длинной” команды состоящей из двух слов (lds Rd,k, jmp k и т.д.) на выполнение операции уйдёт 3 цикла.

Флаги программы регистра состояния также не доступны инструкциям sbis P,b, sbic P,b, но из-за важности их значения предусмотрены две команды условного перехода разработанных специально для работы с SREG: brbs s,k (Переход, если бит регистра SREG установлен), brbc s,k (Переход, если бит регистра SREG сброшен). Когда соответствующий бит s в SREG установлен для brbs s,k или сброшен для brbс s,k производится относительный переход в пределах +63…-63 слов (PC+k+1).

Читайте также  Вращающиеся трансформаторы бвг и предварительные усилители видеомагнитофонов

Ассемблер AVR поддерживает по 9 различных форм написания инструкций brbs s,k, brbc s,k для разных значений флагов программы (табл.4).

Табл 4. Команды условных переходов по состоянию флагов SREG:

Проверка
флага

Команда условного
перехода

Альтернативная
Форма написания

Команды передачи управления

Таким образом, команды передачи управления изменяют содержимое регистров cs и eip/ip , в результате чего микропроцессор выбирает для выполнения не следующую по порядку команду программы, а команду в некотором другом участке программы. Конвейер внутри микропроцессора при этом сбрасывается.


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

  1. Команды безусловной передачи управления:
    • команда безусловного перехода;
    • вызова процедуры и возврата из процедуры;
    • вызова программных прерываний и возврата из программных прерываний.
  2. Команды условной передачи управления:
    • команды перехода по результату команды сравнения cmp ;
    • команды перехода по состоянию определенного флага;
    • команды перехода по содержимому регистра ecx/cx.
  3. Команды управления циклом:
    • команда организации цикла со счетчиком ecx/cx;
    • команда организации цикла со счетчиком ecx/cx с возможностью досрочного выхода из цикла по дополнительному условию.

Безусловные переходы

Модификатор может принимать следующие значения:

  • near ptr — прямой переход на метку внутри текущего сегмента кода. Модифицируется только регистр eip/ip (в зависимости от заданного типа сегмента кода use16 или use32) на основе указанного в команде адреса (метки) или выражения, использующего символ извлечения значения СчА — $;
  • far ptr — прямой переход на метку в другом сегменте кода. Адрес перехода задается в виде непосредственного операнда или адреса (метки) и состоит из 16-битного селектора и 16/32-битного смещения, которые загружаются, соответственно, в регистры cs и ip/eip;
  • word ptr — косвенный переход на метку внутри текущего сегмента кода. Модифицируется (значением смещения из памяти по указанному в команде адресу, или из регистра) только eip/ip. Размер смещения 16 или 32 бит;
  • dword ptr — косвенный переход на метку в другом сегменте кода. Модифицируются (значением из памяти — и только из памяти, из регистра нельзя) оба регистра, cs и eip/ip. Первое слово/двойное слово этого адреса представляет смещение и загружается в ip/eip; второе/третье слово загружается в cs.

Команда безусловного перехода jmp

Адрес_перехода представляет собой адрес в виде метки либо адрес области памяти, в которой находится указатель перехода.

Всего в системе команд микропроцессора есть несколько кодов машинных команд безусловного перехода jmp .
Их различия определяются дальностью перехода и способом задания целевого адреса.
Дальность перехода определяется местоположением операнда адрес_перехода. Этот адрес может находиться в текущем сегменте кода или в некотором другом сегменте. В первом случае переход называется внутрисегментным, или близким, во втором — межсегментным, или дальним.
Внутрисегментный переход предполагает, что изменяется только содержимое регистра eip/ip .
Можно выделить три варианта внутрисегментного использования команды jmp:

  • прямой короткий;
  • прямой;
  • косвенный.

Процедуры

Для описания последовательности команд в виде процедуры в языке ассемблера используются две директивы: PROC и ENDP .

Синтаксис описания процедуры таков (рис. 1).

Рис. 1. Синтаксис описания процедуры в программе

Из рис. 1 видно, что в заголовке процедуры (директиве PROC) обязательным является только задание имени процедуры. Среди большого количества операндов директивы PROC следует особо выделить [расстояние] .
Этот атрибут может принимать значения near или far и характеризует возможность обращения к процедуре из другого сегмента кода. По умолчанию атрибут [расстояние] принимает значение near .

Процедура может размещаться в любом месте программы, но так, чтобы на нее случайным образом не попало управление. Если процедуру просто вставить в общий поток команд, то микропроцессор будет воспринимать команды процедуры как часть этого потока и соответственно будет осуществлять выполнение команд процедуры.
Более подробно вопросы, связанные с описанием и использованием процедур в программах ассемблера, рассматриваются на уроках 10 и 14. Примеры использования процедур вы можете посмотреть в приложении 7.

Условные переходы

Микропроцессор имеет 18 команд условного перехода (см. “Описание команд”). Эти команды позволяют проверить:

  • отношение между операндами со знаком (“больше — меньше”);
  • отношение между операндами без знака (“выше — ниже”)2;
  • состояния арифметических флагов zf, sf, cf, of, pf (но не af).

Команды условного перехода имеют одинаковый синтаксис:
jcc метка_перехода

Как видно, мнемокод всех команд начинается с “ j ” — от слова jump (прыжок), cc — определяет конкретное условие, анализируемое командой.
Что касается операнда метка_перехода, то эта метка может находится только в пределах текущего сегмента кода, межсегментная передача управления в условных переходах не допускается . В связи с этим отпадает вопрос о модификаторе, который присутствовал в синтаксисе команд безусловного перехода. В ранних моделях микропроцессора (i8086, i80186 и i80286) команды условного перехода могли осуществлять только короткие переходы — на расстояние от –128 до +127 байт от команды, следующей за командой условного перехода. Начиная с модели микропроцессора 80386 это ограничение снято, но, как видите, только в пределах текущего сегмента кода.

Для того чтобы принять решение о том, куда будет передано управление командой условного перехода, предварительно должно быть сформировано условие, на основании которого и будет приниматься решение о передаче управления.
Источниками такого условия могут быть:

  • любая команда, изменяющая состояние арифметических флагов;
  • команда сравнения cmp , сравнивающая значения двух операндов;
  • состояние регистра ecx/cx.

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

Команда сравнения cmp

Синтаксис команды cmp:
cmp операнд_1,операнд_2 (compare) — сравнивает два операнда и по результатам сравнения устанавливает флаги.

Флаги, устанавливаемые командой cmp , можно анализировать специальными командами условного перехода. Прежде чем мы их рассмотрим, уделим немного внимания мнемонике этих команд условного перехода (табл. 1). Понимание обозначений при формировании названия команд условного перехода (элемент в названии команды jcc , обозначенный нами cc ) облегчит их запоминание и дальнейшее практическое использование.

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


Команды условного перехода и регистр ecx/cx

Эти команды очень удобно использовать при организации цикла и при работе с цепочками символов.
Нужно отметить ограничение, свойственное команде jcxz/jecxz . В отличие от других команд условной передачи управления, команда jcxz/jecxz может адресовать только короткие переходы — на –128 байт или на +127 байт от следующей за ней команды.

Организация циклов

loop метка_перехода (Loop) — повторить цикл. Команда позволяет организовать циклы, подобные циклам for в языках высокого уровня с автоматическим уменьшением счетчика цикла. Работа команды заключается в выполнении следующих действий:

  • декремента регистра ecx/cx;
  • сравнения регистра ecx/cx с нулем:
    • если (ecx/cx) > 0, то управление передается на метку перехода;
    • если (ecx/cx) = 0, то управление передается на следующую после loop команду.


loope/loopz метка_перехода (Loop till cx <> 0 or Zero Flag = 0) — повторить цикл, пока cx <> 0 или zf = 0.
Команды loope и loopz — абсолютные синонимы, поэтому используйте ту команду, которая вам больше нравиться. Работа команд заключается в выполнении следующих действий:

  • декремента регистра ecx/cx;
  • сравнения регистра ecx/cx с нулем;
  • анализа состояния флага нуля zf:
    • если (ecx/cx) > 0 и zf = 1, управление передается на метку перехода;
    • если (ecx/cx) = 0 или zf = 0, управление передается на следующую после loop команду.

loopne/loopnz метка_перехода (Loop till cx <> 0 or Not Zero flag=0) — повторить цикл пока cx <> 0 или zf = 1.
Команды loopne и loopnz также абсолютные синонимы. Работа команд заключается в выполнении следующих действий:

  • декремента регистра ecx/cx;
  • сравнения регистра ecx/cx с нулем;
  • анализа состояния флага нуля zf:
    • если (ecx/cx) > 0 и zf = 0, управление передается на метку перехода;
    • если (ecx/cx)=0 или zf=1, управление передается на следующую после loop команду.

Команды loope/loopz и loopne/loopnz по принципу своей работы являются взаимообратными. Они расширяют действие команды loop тем, что дополнительно анализируют флаг zf, что дает возможность организовать досрочный выход из цикла, используя этот флаг в качестве индикатора.

Недостаток команд организации цикла loop, loope/loopz и loopne/loopnz в том, что они реализуют только короткие переходы (от –128 до +127 байт). Для работы с длинными циклами придется использовать команды условного перехода и команду jmp, поэтому постарайтесь освоить оба способа организации циклов.

Команды передачи управления

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

1. Команды безусловной передачи управления:

— вызова программных прерываний и возврата из программных прерываний. Int, iret

2. Команды условной передачи управления:

команды перехода по результату команды сравнения cmp;

— команды перехода по состоянию определенного флага;

— команды перехода по содержимому регистра ecx/cx.

— команда организации цикла со счетчиком ecx/cx;

— команда организации цикла со счетчиком ecx/cx с возможностью досрочного выхода из цикла по дополнительному условию.

jmp адрес_перехода — безусловный переход без сохранения информации о точке возврата. Аналог goto.

Условные переходы

Команды условного перехода имеют одинаковый синтаксис:

jcc метка_перехода

Мнемокод всех команд начинается с “j” — от слова jump (прыжок), cc — определяет конкретное условие, анализируемое командой. Что касается операнда метка_перехода, то эта метка может находится только в пределах текущего сегмента кода, межсегментная передача управления в условных переходах не допускается.

Для того чтобы принять решение о том, куда будет передано управление командой условного перехода, предварительно должно быть сформировано условие, на основании которого и будет приниматься решение о передаче управления. Источниками такого условия могут быть:

— любая команда, изменяющая состояние арифметических флагов;

— команда сравнения cmp, сравнивающая значения двух операндов;

— состояние регистра ecx/cx.

Условные переходы по содержимому флагов

Название флага Номер бита в eflags/flag Команда условного перехода Значение флага для осуществления перехода
Флаг переноса cf 1 jc cf = 1
Флаг четности pf 2 jp pf = 1
Флаг нуля zf 6 jz zf = 1
Флаг знака sf 7 js sf = 1
Флаг переполнения of 11 jo of = 1
Флаг переноса cf 1 jnc cf = 0
Флаг четности pf 2 jnp pf = 0
Флаг нуля zf 6 jnz zf = 0
Флаг знака sf 7 jns sf = 0
Флаг переполнения of 11 jno of = 0

jcxz метка_перехода (Jump if cx is Zero) — переход, если cx ноль;

jecxz метка_перехода (Jump Equal ecx Zero) — переход, если ecx ноль.

Пример программы: определите, равны ли два числа вводимые пользователем с клавиатуры.

Model small

Stack 100h

Data

s1 db ‘числа равны$’

s2 db ‘числа не равны$’

int 21h ;ввели первое число

int 21h ;ввели второе число

sub al,dl ;сравнили числа

mov dx, offset s1

m1: mov dx, offset s2

int 21h ;выводим информационную строку

Mov ax ,4 c 00 h

Int 21h

End start

Команда сравнения cmp

cmp операнд_1,операнд_2 — сравнивает два операнда и по результатам сравнения устанавливает флаги. Команда сравнения cmp имеет интересный принцип работы. Он абсолютно такой же, как и у команды вычитания sub. Единственное, чего она не делает — это запись результата вычитания на место первого операнда.

Алгоритм работы:

-выполнить вычитание (операнд1-операнд2);

-в зависимости от результата установить флаги, операнд1 и операнд2 не изменять (то есть результат не запоминать).

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

Типы операндов Мнемокод команды условного перехода Критерий условного перехода Значения флагов для осществления перехода
Любые je операнд_1 = операнд_2 zf = 1
Любые jne операнд_1<>операнд_2 zf = 0
Со знаком jl/jnge операнд_1 of
Со знаком jle/jng операнд_1 of or zf = 1
Со знаком jg/jnle операнд_1 > операнд_2 sf = of and zf = 0
Со знаком jge/jnl операнд_1 => операнд_2 sf = of
Без знака jb/jnae операнд_1 операнд_2 cf = 0 and zf = 0
Без знака jae/jnb операнд_1 => операнд_2 cf = 0

Пример программы: определите, равны ли два числа вводимые пользователем с клавиатуры.

Model small

Stack 100h

Data

s1 db ‘числа равны$’

s2 db ‘числа не равны$’

int 21h ;ввели первое число

int 21h ;ввели второе число

cmp al,dl ;сравнили числа

mov dx, offset s1

m1: mov dx, offset s2

int 21h ;выводим информационную строку

Mov ax ,4 c 00 h

Int 21h

end start

Организация циклов

loop метка_перехода (Loop) — повторить цикл

Работа команды заключается в выполнении следующих действий:

— декремента регистра ecx/cx;

— сравнения регистра ecx/cx с нулем:

— если (ecx/cx) > 0, то управление передается на метку перехода;

— если (ecx/cx) = 0, то управление передается на следующую после loop команду

loope/loopz метка_перехода (Loop till cx <> 0 or Zero Flag = 0) — повторить цикл, пока cx <> 0 или zf = 0.

loopne/loopnz метка_перехода (Loop till cx <> 0 or Not Zero flag=0) — повторить цикл пока cx <> 0 или zf = 1

Недостаток команд организации цикла loop, loope/loopz и loopne/loopnz в том, что они реализуют только короткие переходы (от –128 до +127 байт).

Организация вложенных циклов

mov cх,n ; в сх заносим количество итераций внешнего цикла

mov cx,n1; в сх заносим количество итераций внутреннего цикла

тело внутреннего цикла

Пример программы: Напишите программу подсчета у=1+2+3+…+n, n не более 10000.

s1 db ‘введите n’,10,13,’$’

mov dx, offset s1

m: shl bx,4

int 21h вводим n в регистр bx

xor dx,dx

m1: add dx,cx считаем у

Цепочечные команды

(Команды обработки строк символов)

Цепочка – это последовательность элементов, размер которых может быть байт, слово, двойное слово. Содержимое этих элементов может быть любое – символы, числа.

В системе команд микропроцессора имеется семь операций-примитивов обработки цепочек.

Каждая из них реализуется в микропроцессоре тремя командами, в свою очередь, каждая из этих команд работает с соответствующим размером элемента — байтом, словом или двойным словом.

Вместе с цепочечными командами обычно применяют префиксы повторений, которые ставятся перед командой в поле [метки]. Цепочечная команда без префикса выполняется один раз. С префиксом цепочечные команды выполняются циклично.

rep (REPeat) — команда выполняется, пока содержимое в ecx/cx не станет равным 0. При этом цепочечная команда, перед которой стоит префикс, автоматически уменьшает содержимое ecx/cx на единицу. Та же команда, но без префикса, этого не делает.

repe или repz (REPeat while Equal or Zero) — команда выполняется до тех пор, пока содержимое ecx/cx не равно нулю или флаг zf равен 1. Как только одно из этих условий нарушается, управление передается следующей команде программы

repne или repnz (REPeat while Not Equal or Zero) — команда циклически выполняется до тех пор, пока содержимое ecx/cx не равно нулю или флаг zf равен нулю. При невыполнении одного из этих условий работа команды прекращается.

Формирования физического адреса операндов адрес_источника и адрес_приемника происходит следующим образом:

адрес_источника — пара ds:esi/si;

адрес_приемника — пара es:edi/di

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

— от начала цепочки к ее концу, то есть в направлении возрастания адресов;

— от конца цепочки к началу, то есть в направлении убывания адресов.

Цепочечные команды сами выполняют модификацию регистров, адресующих операнды, обеспечивая тем самым автоматическое продвижение по цепочке. Количество байт, на которые эта модификация осуществляется, определяется кодом команды. А вот знак этой модификации определяется значением флага направления df (Direction Flag) в регистре eflags/flags. Состоянием флага df можно управлять с помощью двух команд, не имеющих операндов:

cld (Clear Direction Flag) — очистить флаг направления df = 0, значение индексных регистров esi/si и edi/di будет автоматически увеличиваться (операция инкремента) цепочечными командами, то есть обработка будет осуществляться в направлении возрастания адресов;

std (Set Direction Flag) — установить флаг направления df = 1, то значение индексных регистров esi/si и edi/di будет автоматически уменьшаться (операция декремента) цепочечными командами, то есть обработка будет идти в направлении убывания адресов.

Типовой набор действий для выполнения любой цепочечной команды:

— Установить значение флага df в зависимости от того, в каком направлении будут обрабатываться элементы цепочки — в направлении возрастания или убывания адресов.

— Загрузить указатели на адреса цепочек в памяти в пары регистров ds:(e)si и es: (e)di.

— Загрузить в регистр ecx/cx количество элементов, подлежащих обработке.

— Выдать цепочечную команду с префиксом повторений.

Пересылка цепочек

movs адрес_прием, адрес_источника (MOVe String)- переслать цепочку;

movsb MOVe String Byte) — переслать цепочку байт;

movsw (MOVe String Word) — переслать цепочку слов;

movsd (MOVe String Double word) — переслать цепочку двойных слов.

Команда копирует байт, слово или двойное слово из цепочки источника, в цепочку приемника. Размер пересылаемых элементов ассемблер определяет, исходя из атрибутов идентификаторов. К примеру, если эти идентификаторы были определены директивой db, то пересылаться будут байты, если идентификаторы были определены с помощью директивы dd, то пересылке подлежат двойные слова.

Для цепочечных команд с операндами типа movs адрес_приемника,адрес_источника, не существует машинного аналога. При трансляции в зависимости от типа операндов транслятор преобразует ее в одну из трех машинных команд: movsb, movsw или movsd.

Сама по себе команда movs пересылает только один элемент, исходя из его типа, и модифицирует значения регистров esi/si и edi/di. Если перед командой написать префикс rep, то одной командой можно переслать до 64 Кбайт данных. Число пересылаемых элементов должно быть загружено в счетчик — регистр cx (use16) или ecx (use32).

Пример проги. Пересылка строк командой movs

mov ax,@data ;загрузка сегментных регистров

mov ds,ax ;настройка регистров DS и ES на адрес сегмента данных

cld ;сброс флага DF — обработка строки от начала к концу

lea si,source ;загрузка в si смещения строки-источника

lea di,dest ;загрузка в DS смещения строки-приёмника

mov cx,20 ;для префикса rep — счетчик повторений (длина строки)

rep movs dest,source ;пересылка строки

mov ah,09h ;вывод на экран строки-приёмника

Команды передачи управления на языке ассемблера

Главная > Лекция >Информатика, программирование

Команды передачи управления на языке ассемблера

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

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

условным — решение о том, какая команда будет выполняться следующей, принимается на основе анализа некоторых условий или данных.

Как вы помните, программа представляет собой последовательность команд и данных, занимающих определенное пространство оперативной памяти. Эта пространство памяти может быть либо непрерывным, либо состоять из нескольких фрагментов.

На уроке 5 нами были рассмотрены средства организации фрагментации кода программы и ее данных на сегменты. То, какая команда программы должна выполняться следующей, микропроцессор узнает по содержимому пары регистров cs:(e)ip :

cs — сегментный регистр кода, в котором находится физический (базовый) адрес текущего сегмента кода;

eip/ip — регистр указателя команды, в котором находится значение, представляющее собой смещение в памяти следующей команды, подлежащей выполнению, относительно начала текущего сегмента кода.

Напомню, почему мы записываем регистры eip/ip через косую черту. Какой конкретно регистр будет использоваться, зависит от установленного режима адресации use16 или use32. Если указано use16, то используется ip, если use32, то используется eip.

Таким образом, команды передачи управления изменяют содержимое регистров cs и eip/ip , в результате чего микропроцессор выбирает для выполнения не следующую по порядку команду программы, а команду в некотором другом участке программы. Конвейер внутри микропроцессора при этом сбрасывается.

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

Команды безусловной передачи управления:

команда безусловного перехода;

вызова процедуры и возврата из процедуры;

вызова программных прерываний и возврата из программных прерываний.

Команды условной передачи управления:

команды перехода по результату команды сравнения cmp ;

команды перехода по состоянию определенного флага;

команды перехода по содержимому регистра ecx/cx.

Команды управления циклом:

команда организации цикла со счетчиком ecx/cx;

команда организации цикла со счетчиком ecx/cx с возможностью досрочного выхода из цикла по дополнительному условию.

Безусловные переходы

Предыдущее обсуждение выявило некоторые детали механизма перехода. Команды перехода модифицируют регистр указателя команды eip/ip и, возможно, сегментный регистр кода cs . Что именно должно подвергнуться модификации, зависит:

от типа операнда в команде безусловного перехода (ближний или дальний);

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

Модификатор может принимать следующие значения:

near ptr — прямой переход на метку внутри текущего сегмента кода. Модифицируется только регистр eip/ip (в зависимости от заданного типа сегмента кода use16 или use32) на основе указанного в команде адреса (метки) или выражения, использующего символ извлечения значения СчА — $;

far ptr — прямой переход на метку в другом сегменте кода. Адрес перехода задается в виде непосредственного операнда или адреса (метки) и состоит из 16-битного селектора и 16/32-битного смещения, которые загружаются, соответственно, в регистры cs и ip/eip;

word ptr — косвенный переход на метку внутри текущего сегмента кода. Модифицируется (значением смещения из памяти по указанному в команде адресу, или из регистра) только eip/ip. Размер смещения 16 или 32 бит;

dword ptr — косвенный переход на метку в другом сегменте кода. Модифицируются (значением из памяти — и только из памяти, из регистра нельзя) оба регистра, cs и eip/ip. Первое слово/двойное слово этого адреса представляет смещение и загружается в ip/eip; второе/третье слово загружается в cs.

Команда безусловного перехода jmp

Синтаксис команды безусловного перехода

jmp [модификатор] адрес_перехода — безусловный переход без сохранения информации о точке возврата.

Адрес_перехода представляет собой адрес в виде метки либо адрес области памяти, в которой находится указатель перехода.

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

Их различия определяются дальностью перехода и способом задания целевого адреса.

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

Внутрисегментный переход предполагает, что изменяется только содержимое регистра eip/ip .

Можно выделить три варианта внутрисегментного использования команды jmp:

Процедуры

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

Процедура , часто называемая также подпрограммой , — это основная функциональная единица декомпозиции (разделения на несколько частей) некоторой задачи.

Процедура представляет собой группу команд для решения конкретной подзадачи и обладает средствами получения управления из точки вызова задачи более высокого уровня и возврата управления в эту точку.

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

Для описания последовательности команд в виде процедуры в языке ассемблера используются две директивы: PROC и ENDP .

Синтаксис описания процедуры таков (рис. 1).

Рис. 1. Синтаксис описания процедуры в программе

Из рис. 1 видно, что в заголовке процедуры (директиве PROC) обязательным является только задание имени процедуры. Среди большого количества операндов директивы PROC следует особо выделить [расстояние] .

Этот атрибут может принимать значения near или far и характеризует возможность обращения к процедуре из другого сегмента кода. По умолчанию атрибут [расстояние] принимает значение near .

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

Более подробно вопросы, связанные с описанием и использованием процедур в программах ассемблера, рассматриваются на уроках 10 и 14. Примеры использования процедур вы можете посмотреть в приложении 7.

Условные переходы

Микропроцессор имеет 18 команд условного перехода (см. “Описание команд”). Эти команды позволяют проверить:

отношение между операндами со знаком (“больше — меньше”);

отношение между операндами без знака (“выше — ниже”)2;

состояния арифметических флагов zf, sf, cf, of, pf (но не af).

Команды условного перехода имеют одинаковый синтаксис:

Как видно, мнемокод всех команд начинается с “ j ” — от слова jump (прыжок), cc — определяет конкретное условие, анализируемое командой.

Что касается операнда метка_перехода , то эта метка может находится только в пределах текущего сегмента кода, межсегментная передача управления в условных переходах не допускается . В связи с этим отпадает вопрос о модификаторе, который присутствовал в синтаксисе команд безусловного перехода. В ранних моделях микропроцессора (i8086, i80186 и i80286) команды условного перехода могли осуществлять только короткие переходы — на расстояние от –128 до +127 байт от команды, следующей за командой условного перехода. Начиная с модели микропроцессора 80386 это ограничение снято, но, как видите, только в пределах текущего сегмента кода.

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

Источниками такого условия могут быть:

любая команда, изменяющая состояние арифметических флагов;

команда сравнения cmp , сравнивающая значения двух операндов;

состояние регистра ecx/cx.

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

Команда сравнения cmp

Команда сравнения cmp имеет интересный принцип работы. Он абсолютно такой же, как и у команды вычитания.

sub операнд_1,операнд_2 . Команда cmp так же, как и команда sub , выполняет вычитание операндов и устанавливает флаги. Единственное, чего она не делает — это запись результата вычитания на место первого операнда.

Синтаксис команды cmp:

cmp операнд_1,операнд_2 (compare) — сравнивает два операнда и по результатам сравнения устанавливает флаги.

Флаги, устанавливаемые командой cmp , можно анализировать специальными командами условного перехода. Прежде чем мы их рассмотрим, уделим немного внимания мнемонике этих команд условного перехода (табл. 1). Понимание обозначений при формировании названия команд условного перехода (элемент в названии команды jcc , обозначенный нами cc ) облегчит их запоминание и дальнейшее практическое использование.

Таблица 1. Значение аббревиатур в названии команды jcc