Чем отличаются команды ret и reti
Перейти к содержимому

Чем отличаются команды ret и reti

  • автор:

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

Команды группы переходов можно подразделить на 3 подгруппы. Первая подгруппа — безусловные переходы. Список команд этой подгруппы приведён в табл. 7.7.

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

Переход по адресу

Переход по @A+DPIR

Вызов подпрограммы по адресу

Возврат из подпрограммы

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

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

Для короткого перехода (Short JMP, Short — короткий) адрес перехода определяется смещением, в качестве которого выступает второй байт команды. Этот байт интерпретируется как число со знаком, что обеспечивает переход на величину от -128 до +127 байт относительно адреса команды, следующей за инструкцией S JMP.

Инструкция длинного перехода L JMP (Long JMP, Long — длинный) имеет длину в три байта, причём два последних байта представляют адрес. Эта команда дает возможность перехода к любому адресу из 64 Кбайт памяти программ.

Команда среднего перехода (Average JMP, Average — средний) является двухбайтной. Первый байт помимо кода операции содержит 3 бита адреса перехода, а второй байт — остальные 8 бит адреса перехода. При выполнении команды AJMP эти 11 бит подставляются в 11 младших разрядов PC, а старшие 5 бит остаются без изменений. Следовательно, переход возможен в пределах блока в 2 Кбайт, в котором расположена команда AJMP.

Во всех случаях программисту следует описывать адрес перехода или в виде метки, или в виде 16-битной константы. Ассемблер сам подставит корректный формат адреса.

Инструкция JMP @A+DPTR предназначена для выполнения переходов по таблице. В момент выполнения команды адрес перехода вычисляется как сумма содержимого шестнадцатибитного DPTR и содержимого аккумулятора. Обычно DPTR устанавливается на адрес таблицы переходов, а в аккумуляторе находится смещение (индекс) относительно начала таблицы. Практический пример использования этой команды приведен ниже:

MOV DPTR, #JUMP_TABLE

MOV A, INDEX_NUMBER

RL А /обеспечивается двухбайтовый интервал

;при последовательных значениях номера /индекса (0,1,2,3. )

По аналогии с командой JMP команда CALL addr имеет две формы: короткую и среднюю: LCALL и ACALL. Все замечания относительно форматов JMP верны и для CALL.

Единственное различие команд RET и RETI заключается в том, что при выполнении команды RETI система организации прерываний уведомляется об окончании подпрограммы прерываний.

Вторая подгруппа — условные переходы. Их характеристики приведены в табл.7.8. Все команды этой подгруппы выполняют короткий переход и содержат байт смещения, который из-за отсутствия места в табл. 7.8 не показан. Отметим, что переход по нулевому/ненулевому условию производится на основе содержимого аккумулятора, а флаг Z в слове состояния программы отсутствует.

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

Чем отличаются команды ret и reti

Все, что необходимо начинающему и опытному программисту

Ячейки, название которых начинается с BOOT, определяют режим начальной загрузки — как я уже упоминал, в современных AVR можно изменять начальный адрес программы и расположение векторов прерываний. Данные ячейки, как и все остальные, следует оставить как есть. В том числе это касается и битов защиты программы (тех самых «предохранительных», которые здесь называются Boot Lock Bits), которые, к сожалению, настоящей защиты не дают, т. к. легко обходятся. Зато неприятностей могут доставить много, поскольку раз запрограммировав их, исправить что-то уже довольно трудно, а для любителя — почти невозможно.

ГЛАВА 6
Система команд AVR
Познакомившись в предыдущей главе с простейшими программами для AVR, мы теперь попробуем рассмотреть систему команд AVR в целом, чтобы понять, какие возможности нам предоставляются. Всего для AVR насчитывается от 90 до 133 команд (в зависимости от контроллера), и только их подробное описание, например в [2], занимает почти 70 страниц. Потому все команды, которые к тому же часто взаимозаменяемы, мы описывать не будем, для этого существуют справочники. С некоторыми из тех команд, что выпадут из рассмотрения в этой главе, мы познакомимся по ходу дела в дальнейшем. Если будете пользоваться [2], то имейте в виду, что в описаниях команд там встречается несколько мелких, но досадных опечаток (по крайней мере, так было в первом издании), и в критичных случаях нужно проверять по англоязычному фирменному оригиналу. Выборочный перечень команд с их краткой характеристикой, достаточный для составления большинства законченных программ, вы также найдете в приложении 2.

Команды передачи управления и регистр SREG
В языках высокого уровня была всего одна команда перехода на метку (GOTO), и то Дейкстра на нее набросился. А в ассемблере AVR таких команд — пруд пруди, более 30! Зачем? На самом деле без доброй половины из них, если не больше, можно обойтись во всех жизненных случаях, т. к. они в значительной степени взаимозаменяемы. Разнообразие это, если угодно, дань памяти великому программисту — для повышения читаемости программ. Мы рассмотрим только ключевые команды из этого перечня. С командами безусловного перехода rjmp и jmp мы уже познакомились достаточно подробно в предыдущей главе в связи с прерываниями, так что сразу перейдем к вызову процедур (официальный язык атмеловских руководств предпочитает консервативный термин подпрограмма — subroutine) — rcaii и call. Синтаксис у них точно такой же, как у команд безусловного перехода, и по сути это тот же самый переход по метке. И разница между этими двумя командами тоже аналогичная — call работает в пределах 64 К адресов памяти (или до 8 М адресов в соответствующем контроллере, поддерживающем такой объем адресного пространства), занимает четыре байта и выполняется за четыре цикла, a rcall годится только для МК с объемом памяти не более 8 кбайт, но занимает два байта и выполняется за три цикла. Мы в дальнейшем будем пользоваться только командой rcall.

Отличаются они от команд безусловного перехода тем, что здесь в момент перехода к процедуре контроллер автоматически сохраняет в стеке адрес текущей команды, чтобы потом знать, куда вернуться (потому длительность выполнения этих команд на такт больше, чем для простого перехода, см. далее). А как МК «узнает», когда именно нужно возвращаться? Для этого каждая процедура-подпрограмма оформляется специальным образом — не отличаясь сначала ничем от любого другого участка программного кода, обозначенного меткой, в месте возврата она должна содержать специальную команду — ret (от return — «возврат»). По этой команде МК извлекает из стека сохраненное содержимое счетчика команд и продолжает выполнение прерванной основной программы. Аналогично обрабатываются прерывания — только специальной команды, как вы знаете, там нет, вызов производится обычным переходом rjmp или jmp, но поскольку он осуществляется с определенного адреса (там, где стоит вектор прерывания), то контроллер делает то же самое — сохраняет в стеке адрес командного счетчика, на котором выполнение основной программы было грубо нарушено, начинает выполнять прерывание и ожидает команды возврата — только здесь она записывается, как reti (return interrupt) — в отличие от ret, эта команда еще и восстанавливает состояние флага прерываний i в регистре SREG.

В самой обширной группе команд передачи управления названия начинаются с букв br, от слова branch — «ветка». Это команды условного перехода, которые считаются одними из самых главных в любой системе программирования, поскольку позволяют организовывать циклы — базовое понятие программистских наук. По смыслу все эти команды сводятся к банальному if . then («если . то»). Мы будем пользоваться лишь некоторыми командами, потому что они во многом взаимозаменяемы. Смысл остальных вам будет понятен из их описания. Наиболее часто употребляется пара brne (Branch if Not Equal, «перейти, если не равно») и breq (Branch if Equal, «перейти, если равно»). Уже из смысла этих команд понятно, как они пишутся — после команды следует метка, на которую нужно перейти. Вопрос только, откуда здесь берется собственно условие? Для этого эти две команды ветвления обязательно употребляют в паре с одной из команд, устанавливающих флаг нуля z в регистре состояния SREG.

Обычно для этой цели используют команду ср (от compare— «сравнить»), которая сравнивает регистры, или cpi («сравнить с непосредственным значением»). Для понимания того, что именно при этом происходит, нужно учесть, что данные команды по сути вычитают второй операнд из первого, отличаясь от команд sub или subi только тем, что результат теряется, а операнды остаются теми же, меняются только значения соответствующих флагов регистра SREG, ИЗ которых нас интересуют в первую очередь флаг нуля z, отрицательного значения N и переноса с.

Указанные флаги устанавливаются не только в результате сравнения, но и при выполнении операций с битами или арифметических операций, когда значение результата, соответственно, становится нулевым, отрицательным или превышает диапазон 8-битового числа (255). Что означают флаги регистра SREG в целом, можно посмотреть в табл. 6.1 (на белом фоне находятся флаги, относящиеся к операциям сравнения, а также к арифметическим операциям).

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru

Система команд микроконтроллеров AVR

Микроконтроллеры (далее — МК) серии AVR имеют от 90 до 120 команд в зависимости от модели. Здесь рассмотрены только те команды, которые использованы в нашей программе.

ADD

Синтаксис: ADD reg1, reg2

Эта команда складывает содержимое регистров reg1 и reg2, сохраняя результат в регистре reg1. Изменяет состояние флагов H, S, V, N, Z, C.

AND

Синтаксис: AND reg1, reg2

Эта команда выполняет операцию «Логическое И» между регистрами reg1 и reg2, сохраняя результат в регистре reg1. Изменяет состояние флагов S, V, N, Z.

ANDI

Синтаксис: ANDI hreg, number

Эта команда выполняет операцию «Логическое И» между содержимым старшего регистра hreg и константой number (0…255), сохраняя результат в регистре. Изменяет состояние флагов S, V, N, Z.

BRBC

Синтаксис: BRBC bit, label

Эта команда проверяет состояние бита регистра SREG ($3F) и переходит к метке label, если бит сброшен. Метка должна находиться в пределах 63 команд от команды brbc.

BRBS

Синтаксис: BRBS bit, label

Эта команда проверяет состояние бита регистра SREG ($3F) и переходит к метке label, если бит установлен. Метка должна находиться в пределах 63 команд от команды brbs.

BRCC

Синтаксис: BRCC bit, label

Эта команда проверяет флаг переноса (С) и переходит к метке label, если он сброшен.

BRCS

Синтаксис: BRCS bit, label

Эта команда проверяет флаг переноса (С) и переходит к метке label, если он установлен.

BREQ

Синтаксис: BREQ bit, label

Эта команда проверяет флаг нуля (Z) и переходит к метке label, если он установлен.

BRNE

Синтаксис: BRNE bit, label

Эта команда проверяет флаг нуля (Z) и переходит к метке label, если он сброшен.

CBI

Синтаксис: CBI ioreg, bit

Эта команда сбрасывает в 0 бит регистра ввода-вывода ioreg ($00…$1F). Номер бита определяет операнд bit.

CLR

Синтаксис: CLR reg

Эта команда сбрасывает все биты регистра reg в 0. Изменяет состояние флагов S, V, N, Z.

CP

Синтаксис: CP reg1, reg2

Эта команда сравнивает содержимое регистров reg1 и reg2 путем вычитания reg2 из reg1. Содержимое регистров не изменяется. Изменяет состояние флагов H, S, V, N, Z, C.

CPI

Синтаксис: CPI hreg, number

Эта команда сравнивает содержимое регистра hreg с константой number путем вычитания константы из регистра. Содержимое регистров не изменяется. Изменяет состояние флагов H, S, V, N, Z, C. Команда работает только с регистрами R16…R31.

DEC

Синтаксис: DEC reg

Эта команда уменьшает на единицу содержимое регистра reg, записывая результат обратно в регистр. Изменяет состояние флагов S, V, N, Z.

IN

Синтаксис: IN reg, ioreg

Эта команда пересылает содержимое регистра ввода-вывода ioreg в РОН reg.

INC

Синтаксис: INC reg

Эта команда увеличивает на единицу содержимое регистра reg, записывая результат обратно в регистр. Изменяет состояние флагов S, V, N, Z.

LD

Синтаксис: LD reg, longreg

Эта команда загружает один байт из памяти данных (адрес ячейки памяти содержится в регистре longer) в регистр reg (для модели 1200).

LDI

Синтаксис: LDI hreg, number

Эта команда загружает непосредственное значение number в старший регистр hreg (команда может работать только с регистрами R16…R31). Число number должно находиться в пределах 0…255.

LSR

Синтаксис: LSR reg

Эта команда выполняет логический сдвиг вправо содержимого регистра reg. При этом 0-й бит копируется в флаг C, 7-й бит сбрасывается в 0. Изменяет состояние флагов S, V, N, Z, C.

ORI

Синтаксис: ORI hreg, number

Эта команда выполняет операцию «Логическое ИЛИ» между содержимым старшего регистра hreg и константой number (0…255), сохраняя результат в регистре. Изменяет состояние флагов S, V, N, Z.

OUT

Синтаксис: OUT ioreg, reg

Эта команда пересылает содержимое регистра общего назначения reg в регистр ввода-вывода ioreg.

RCALL

Синтаксис: RCALL label

Эта команда вызывает подпрограмму, обозначенную меткой label, которая должна находиться в пределах 2048 команд от команды rcall (относительный вызов).

RET

Синтаксис: RET

Эта команда выполняет возврат из подпрограммы, переходя на команду, которая следует за исходной командой call.

RETI

Синтаксис: RETI

Эта команда выполняет возврат из подпрограммы и устанавливает флаг общего разрешения прерываний.

RJMP

Синтаксис: RJMP label

Относительный переход. Выполняет переход к участку программы, обозначенному меткой label, которая должна находиться в пределах 2048 от команды RJMP.

SBI

Синтаксис: SBI ioreg, bit

Эта команда устанавливает в 1 бит регистра ввода-вывода ioreg ($00…$1F). Номер бита определяет операнд bit.

SBIC

Синтаксис: SBIC ioreg, bit

Эта команда проверяет бит регистра ввода-вывода ioreg ($00…$1F) и пропускает следующую команду, если этот бит сброшен. Номер бита определяет операнд bit.

SBIS

Синтаксис: SBIS ioreg, bit

Эта команда проверяет бит регистра ввода-вывода ioreg ($00…$1F) и пропускает следующую команду, если этот бит установлен. Номер бита определяет операнд bit.

SEI

Синтаксис: SEI

Эта команда устанавливает флаг общего разрешения прерываний.

SER

Синтаксис: SER reg

Эта команда устанавливает все биты регистра reg в 1. Изменяет состояние флагов S, V, N, Z. Команда может работать только с регистрами R16…R31.

ST

Синтаксис: ST reg, longreg

Для модели 1200 эта команда сохраняет содержимое регистра reg в памяти данных (адрес ячейки памяти содержится в регистре longer), т.е. косвенно пересылает содержимое РОН reg по адресу, хранящемуся в регистре longer.

SUBI

Синтаксис: SUBI hreg, number

Вычитает из старшего регистра hreg константу number. Результат сохраняется в этом же регистре. Изменяет состояние флагов H, S, V, N, Z, C. Команда может работать только с регистрами R16…R31.

Инструкция RET

В Контакте Ютуб Почта

Инструкция RET в Ассемблере выполняет возврат из ближней процедуры. У этой команды обычно нет операндов, хотя в качестве операнда может быть чётное число (только непосредственное значение).

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

Алгоритм работы команды RET:

  1. Получить из стека IP (адрес возврата в программу из процедуры).
  2. Если имеется операнд, то SP = SP + операнд. Операнд необязателен, но если он есть, то после того, как будет считан адрес возврата, из стека будет удалено столько байтов, сколько указано в операнде. Это требуется, если при вызове процедуры ей передавались параметры через стек.

Никакие флаги при выполнении команды не изменяются.

ВНИМАНИЕ!
В зависимости от того, как была описана процедура, которую завершает команда RET, ассемблер может заменить команду RET на команду RETN или RETF.

Для лучшего понимания смысла и алгоритма работы инструкции RET необходимо разобраться с тем, как вызываются и выполняются процедуры в ассемблере. Но это другая отдельная тема. А сейчас небольшой пример использования:

.model tiny .code ORG 100h start: CALL MyProc ;Вызвать процедуру ADD AX, 1 RET ;Вернуться в операционную систему MyProc PROC ;Объявление процедуры. MOV AX, 1 RET ;Вернуться в программу. MyProc ENDP END start

Ну и напоследок о происхождении названия команды.

RET — это сокращение от слова RETURN (возврат).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *