Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
AVR / 1_Uniproff / Лабораторный практикум 2.doc
Скачиваний:
44
Добавлен:
20.03.2015
Размер:
395.78 Кб
Скачать

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

Цель работы:изучение программных способов маскирования данных и организации условных переходов; исследование особенностей записи и обращения к подпрограммам; изучение методов использования стека при создании программ.

Краткие сведения из теории

Организация условных переходов в МК осуществляется с помощью регистра флагов(статуса, состояния) SREG. Этот регистр имеет 8 разрядов, каждый из которых устанавливается по определенному правилу в соответствии с выполнением МК последней команды. Этими разрядами являются:

  1. Разряд переполнения C – CARRY Flag (флаг переноса) устанавливается и сбрасывается целым рядом операций над данными (арифметические операции, операции сдвига), и его состояние может быть непосредственно программно проверено. Если, например, в результате сложения возник перенос из старшего разряда (7), то он устанавливает флаг переноса. Если же в результате сложения переноса из старшего разряда нет, то флаг переноса сбрасывается.

  2. Разряд нулевого результата Z – ZERO Flag (флаг нуля) устанавливается, если при выполнении арифметической или логической операции во всех разрядах числа в регистре назначения имеются нули. В противном случае – флаг нуля сбрасывается.

  3. Разряд отрицательного числа N – Negative Flag (флаг знака). Байт данных можно интерпретировать как число со знаком, в этом случае седьмой бит считается знаковым. Флаг устанавливается после выполнения операции в соответствии со значением седьмого бита результата.

  4. Разряд переполнения с дополнением V – Two’s complement overflow indicator.

  5. Разряд знака S показывает всегда результат N xor V и используется для определения нестрогих условий (больше либо равно, меньше либо равно).

  6. Разряд половинного переноса H – Half Carry Flag (вспомогательный перенос). Этот флаг свидетельствует о возникновении переноса из третьего разряда в четвертый.

  7. Разряд передачи бита T – Transfer Bit Flag. Этот флаг используется для сохранения/восстановления бита данных. Программно доступен для специальных команд BitLoaD(BLD) и BitSTore (BST).

  8. Разряд прерываний I – Interrupt Flag показывает состояние триггера глобальных прерываний: 1 – прерывания разрешены, 0 – запрещены.

Во многих случаях при выполнении программ необходимо проверять или изменять(маскировать) состояние одного или нескольких разрядов числа в регистре МК. Это можно осуществить с помощью следующих операций:

  1. логического умножения числа в регистре и маски, которая очищает разряд числа, если в соответствующем разряде маски будет записан 0, и не изменяет его, если в разряде маски записана 1;

  2. логического сложения числа в регистре и маски, которое устанавливает разряд числа в 1, если в таком же разряде маски будет записана 1, и не изменяет его, если в этом разряде записан 0;

  3. логического «исключающего ИЛИ» числа в регистре и числа маски, которое инвертирует содержание разряда числа, если в соответствующем разряде маски записана 1, и не изменяет его, если в этом разряде записан 0.

  4. специальных операций по установке и сбросу битов по маске – SBRиCBR, а также специальных операций сохранения и загрузки битовBSTиBLDс использованием регистра статуса.

Примеры использования этих команд приведены в таблице Т-2.1.

Таблица Т-2.1

Мнемокод

Содержимое регистра Rd

Маска K/Rr

Комментарий

Результат

ANDI Rd, K

AND Rd, Rr

00111010

11111111

00000000

10101010

11110000

00001111

00100010

10101100

00100010

00100010

00100010

11111111

11111111

00000000

Логическое умножение содержимого регистра Rdс числомK(или содержимым регистраRr).

00101000

00100010

00000000

00100010

11110000

00001111

00000000

ORI Rd, K

OR Rd, Rr

SBR Rd, K

00111010

00001111

11110000

10101100

00001111

00001111

Логическое сложение содержимого регистра Rdс числомK(или содержимым регистраRr).

Операция установки битов по маске.

10111110

00001111

11111111

EOR Rd,Rr

00111010

00001111

11110000

10101100

00001111

00001111

Логическое “исключающее ИЛИ” содержимого регистра Rdс числомK(или содержимым регистраRr).

10010110

00000000

11111111

CBR Rd,K

00111010

11111111

00000000

10101010

11110000

00001111

00100010

01010011

11011101

11011101

11011101

00000000

00000000

11111111

Операция сброса битов по маске.

00101000

00100010

00000000

00100010

11110000

00001111

00000000

Программа маскирования отдельных разрядов числа, записанного по адресу $0000 (программа П-2.1) приведена ниже. Программа помещает результат маскирования по адресу $0001.

П-2.1

Адрес

Маш. код

Метка

Мнемокод

Комментарий

0000

9100 0000

LDS R16,0x0000

Загрузка байта в R16 с адреса 0x0000

0002

7A0C

ANDI R16,0xAC

Логическое «И» R16 с байтом 0xAC

0003

9300 0001

STS 0x0001,R16

Сохранение результата по адресу 0x0001

0005

9508

RET

Возврат

При выполнении всех логических команд задействуются флаги регистра статуса. Это позволяет проверить состояние любого разряда числа и выполнить условные переходы в программах. Условные переходы организуются в программах с помощью команд условных переходов (Branchif). При выполнении этих команд МК проверяет состояние соответствующего разряда регистра статусаSREG. Если при проверке условие не подтверждается, то выполняется следующая по порядку команда программы. Помимо этого, существуют команды «условного пропуска» (Skipif). Они используются для пропуска одной команды, следующей непосредственно за командой условного пропуска.

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

Ниже приведена программа(П-2.2), которая увеличивает значение регистра R0 на единицу, однако в случае, когда второй разряд установлен в 1, значение регистра увеличивается на 4. Цикл выполняется бесконечно.

П-2.2

Адрес

Маш. код

Метка

Мнемокод

Комментарий

0000

2400

CLR R0

Очистка регистра R0

0001

9403

M0:

INC R0

Увеличиваем R0 на 1 (R0=R0+1)

0002

2D00

MOV R16,R0

Копируем R0 в R16 чтобы не изменять значение в R0

0003

7004

ANDI R16,0x04

Проверяем установлен ли бит 2 в единицу? Если бит не установлен, то результатом логического «И» будет 0, что приведет к установке флага нуля Z=1

0004

F411

BRNE M1

Если Z=0, то переход на метку M1 – прибавляем 4 к R0

0005

940C 0001

JMP M0

Иначе – повторяем цикл, начиная с прибавления 1 к R0

0007

0E00

M1:

ADD R0,R16

Поскольку в регистре R16, после операции ANDI остается значение 4, то мы его и прибавляем к R0

0008

940C 0001

JMP M0

Повторяем цикл

Память микроконтроллера весьма ограничена (2 Кбайт Репрограммируемое ПЗУ, 128 байт EEPROM, Статическое ОЗУ), поэтому при разработке программ нужно стараться сделать их как можно короче. С этой целью часть программы, которая неоднократно повторяется, или программа, которая часто используется, могут быть оформлены в виде подпрограмм – последовательностей команд, выполнение которых может быть вызвано из любого места программы любое количество раз. Процесс передачи управления подпрограмме называется ее вызовом. Данные и адреса, требуемые для работы подпрограммы, называются входными параметрами. Результаты работы подпрограммы, передаваемые по окончании ее работы в основную программу, называются выходными параметрами.

Для вызова подпрограмм и возврата из них используются команды CALL (RCALL, ICALL, EICALL) и RET. Команда CALL загружает в программный счетчик значение своего операнда, при этом МК автоматически сохраняет в стеке адрес основной программы, к которому он будет обращаться после выполнения подпрограммы.

Стек – специально организованная область ОЗУ, задействованная в МК для временного сохранения данных или адресов. Число, записанное в стек последним, извлекается из него первым (Last Input-First Output).

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

Автоматическое сохранение и восстановление адреса основной программы при выполнении подпрограмм позволяет сделать подпрограммы вложенными, т.е. осуществить вызов одной подпрограммы из другой. Уровень вложенности для МК определяется лишь размером стека.

Помимо команд вызова подпрограмм и возврата из них со стеком можно обмениваться информацией с помощью команд PUSH Rr(записать в стек содержимое регистра) и POP Rd(записать данные из стека в регистр). При записи в стек содержимое указателя стека уменьшается (SP=SP-1). При извлечении из стека данные в памяти не изменяются, а лишь происходит их чтение и увеличение указателя стека (SP=SP+1).

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

LDI R16, адрес (например, 0xDF)

STS 0x5D,R16

или

LDI R16, адрес (например, 0xDF)

OUT 0x3D,R16

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

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

Алгоритм работы простой подпрограммы временной задержки приведен на рис.2.1.

Рис 2.1. Алгоритм простой подпрограммы временной задержки

Общее время задержки вычисляется по формуле: , гдеN – число в регистре R16 (параметр подпрограммы). Команда «нет операции» нужна для увеличения времени выполнения цикла, а следовательно и общей задержки. Вместо этой команды может быть записана любая последовательность команд, выполнение которых не изменяет содержимого регистров МК.

Подпрограмма Delay (П-2.3) представляет собой программу временной задержки, в соответствии с алгоритмом на рис. 2.1.

П-2.3

Адрес

Маш. код

Метка

Мнемокод

Комментарий

0000

2E00

Delay:

MOV R0,R16

Копируем значение регистра R16

0001

0000

M1:

NOP

Нет операции

0002

940A

DEC R0

Уменьшаем R0 на 1

0003

F7E9

BRNE M1

Если не 0 (флаг Z не установлен), то переход на метку M1

0004

9508

RET

Выход из подпрограммы

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

П-2.4

Адрес

Маш. код

Метка

Мнемокод

Комментарий

0000

ED0F

LDI R16,0xDF

Определяем область стека, начиная с 0xDF

0001

BF0D

OUT 0x3D,R16

Устанавливаем указатель стека

0002

E015

LDI R17,0x05

Регистр R17 – внешний счетчик, устанавливаем равным 5

0003

2700

CNT0:

CLR R16

Очистка входного параметра R16 для Delay (максимальная задержка)

0004

D003

RCALL Delay

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

0005

951A

DEC R17

Уменьшаем внешний счетчик на 1

0006

F7E1

BRNE CNT0

Если в R17 не получен 0, то переход на CNT0

0007

CFFF

M0:

RJMP M0

Бесконечный цикл

С помощью стека можно осуществлять неявную передачу управления в программе. Это достигается нестандартным использованием команд RET, RJMP/IJMP, POP и PUSH.

  1. Пример неявного вызова (CALL) подпрограммы Delay. После выполнения подпрограммы, необходимо передать управление по адресу Metka. Для этого заносим в стек сначала младший байт адреса, затем старший и передаем управление подпрограмме Delay с помощью команды RJMP, а не RCALL. По команде RET в подпрограмме, МК извлечет из стека адрес возврата (Metka) и передаст управление по этому адресу.

ldi R16,0xDF

out 0x3D,R16

ldi R16,Low(Metka)

push R16

ldi R16,High(Metka)

push R16

rjmp Delay

Metka: nop

  1. Пример неявного возврата из подпрограммы (RET). Изменим подпрограмму Delay так, чтобы в ней отсутствовала команда RET, но передача управления вызывающей программе осуществлялась. Для этого извлечем из стека адрес возврата в регистры R31 и R30 (эти два регистра образуют регистровую пару Z, используемую для косвенной адресации). Затем выполним команду косвенного перехода IJMP, которая передаст управление по адресу R31:R30, то есть в вызывающую программу.

Delay: mov R0,R16

M1: nop

dec R0

brne M1

pop R31

pop R30

ijmp

  1. Пример неявной непосредственной передачи управления (JMP) осуществляется достаточно просто. Для этого необходимо поместить адрес, куда необходимо передать управление, в стек и вызвать команду RET:

ldi R16,Low(Metka)

push R16

ldi R16,High(Metka)

push R16

ret

...

Metka: nop

...

Соседние файлы в папке 1_Uniproff