Разработка алгоритмов работы и программного обеспечения микропроцессорных вычислительных устройств
Задание
программный обеспечение макрос регистр
Написать программное обеспечение на языке
ассемблер для AVR-МК ATmega16,
которое бы позволяло осуществлять вычисление функции:
,
где - число из множества целых чисел в
диапазоне [0, 250];
- число из множества целых чисел в
диапазоне [0, 100];
- число из множества целых чисел в
диапазоне [0, 40000];
Значение функции после
вычисления должно сохраняться в любых ячейках пользовательского ОЗУ.
Вычисление функции оформить в
виде макроса. Входными параметрами макроса должны быть числа , , и адрес ОЗУ
для сохранения значения функции.
В программе поочередно вызвать
макрос для вычисления значений функции для входных аргументов:
) ;
) ;
) .
Адреса ячеек ОЗУ для задать
самостоятельно и указать в пояснительной записке.
Копии экранов с окнами среды AVR Studio,
отображающими размещение исходных данных и полученных результатов в ОЗУ,
привести в пояснительной записке.
Вычисление «вручную»
1. ;
;
;
Перевод целой части числа заключается в
последовательном делении на основание системы на которую осуществляется
перевод, до тех пор, пока результат частного деления не станет меньше основания
системы с записью в обратном порядке частных остатков от делений.
/2 (0) =
50/2 (0) = 25/2 (1) =
12/2 (0) = 6/2 (0) =
3/2 (1) = 1/2 (1);
.
250/2 (0) = 125/2 (1) = 62/2 (0) = 31/ 2
(1) = 15/2 (1) = 7/2 (1) = 3/2 (1) = 1/2 (1);
Перемножим
Проверка условия ;
Вычисление = .
2. ;
;
;
10/2 (0) = 5/2 (1) = 2/2 (0) = ½ (1);
Перемножим
Проверка условия ;
Вычисление = .
Воспользовались правилом переноса со
старших разрядов, правилом вычитания 10 - 1 = 1.
3. ;
;
;
/2 (0) = 35/2 (1) = 17/2 (1) = 8/2 (0) =
4/2 (0) = 2/2 (0) = ½ (1);
50/2 (0) = 25/2 (1) = 12/2 (0) = 6/2 (0)
= 3/2 (1) = ½ (1);
Перемножим
Проверка условия ;
Вычисление = .
Исходный код программы
;******************************************************************
;* Д/З *
;* Версия: 1.0 *
;* Дата: 17.05.2014 *
;* Автор: Момот О.А. *
;* МК: ATmega16 *
;* Fтакт: 10МГц *
;*****************************************************************
; // Псевдокоманды управления
.DEVICE ATmega16; //
Выбор устройства
.NOLIST; //
Выключение листинга
.INCLUDE "m16def.inc"; //
Присоединение файла описаний
.LIST; //
Включение листинга
.DEF temp = R21; //
Определение главного рабочего регистра
.DEF valueK = R23; //
Определение регистра для значения K
.DEF valueX = R24; //
Определение регистра для значения X
.DEF valueBLow = R25; //
Определение регистра для значения B (младшего б.)
.DEF valueBHigh = R26; //
Определение регистра для значения B (старшего б.)
.DEF valueYLow = R27; //
Определение регистра для значения Y (младшего б.)
.DEF valueYHigh = R28; //
Определение регистра для значения Y (старшего б.)
.DEF valueYHighHigh = R29; //
Определение регистра для значения Y (старшего б. R28)
; // Начало
макроса
operationY
.MACRO operationY;
mul
valueK, valueX; //
k*xR1, valueBHigh; //
Сравнение
R1, valueBHighvariantTwo; //
Если
k*x = bR1, valueBHigh; //
Сравнение
R1, valueBHigh
brmi variantOne; //
Если
k*x < bvariantTwoO; //
Если
k*x > b
; // Вариант
k*x <= b:valueBLow, R0; // Сложение
valueBLow, R0valueBHigh, R1; // Сложение
valueBHigh, R1valueYLow, valueBLow; // Копирование
valueYLow = valueBLowvalueYHigh, valueBHigh; //
Копирование
valueYHigh = valueBHigh
; // Вариант
k*x > b:R0, valueBLow; // Сравнение
R0, valueBLowvariantTwoO; // Если
+ переходvariantOne; //
Если
- переход: //
Метка
variantTwoOR0, valueBlow; // Вычитание
R0 - valueBLowR1, valueBHigh; // Вычитание
R1 - valueBHighvalueYLow, R0; // Копирование
valueYLow = R0valueYHigh, R1; // Копирование
valueYHigh = R1
rjmp outMacro; //
Переход на метку outMacro
; // Метка outMacro:
; // Конец макроса operationY
.ENDMACRO;
; // Определим значения операторов макроса @0 -
адрес ячейки ОЗУ для valueYLow,
; @1
- адрес ячейки ОЗУ для valueYHigh,
; @2 -
адрес ячейки ОЗУ для valueYHighHigh.
; // Начало
макроса
outValues
.MACRO outValues;@0, valueYLow; //
Загрузка
@0 = valueYLow @1, valueYHigh; //
Загрузка
@1 = valueYHighvalueYLow; //
Очистка
valueYLowvalueYHigh; //
Очистка
valueYHigh
; // Конец макроса
.ENDMACRO;
; // Определим значения операторов макроса @0 -
значение для valueK,
; @1 -
значение для valueX,
; @2 -
значение для valueBLow,
; @3 -
значение для valueBHigh.
; // Начало макроса ldiRegister
.MACRO ldiRegistervalueK, @0; //
Загрузка
valueK = @0valueX, @1; //
Загрузка
valueX = @1valueBLow, Low(@2); //
Загрузка
valueBLow = @2valueBHigh, High(@2); //
Загрузка
valueBHigh = @3
; // Конец макроса
.ENDMACRO;
; // Начало программного сегмента
.CSEG; //
Выбор сегмента программного кода
.ORG 0; //
Установка текущего адреса в ноль
; // Инициализация стекаtemp, Low(RAMEND); //
Установка младшего б. указателя стека
out SPL, temp; //
Запись
в
SPL = temp
ldi temp, High(RAMEND); //
Установка старшего б. указателя стека
out SPH, temp; //
Запись
в
SPH = temp
; // Вызов
макроса
ldiRegister100, 10, 2500; //
k = 1000, x = 10, b = 2500
; // Вызов
макроса
operationY;
; // Вызов
макроса
out Values$60, $61;
; // Холостая
команда;
; // Вызов
макроса
ldiRegister1, 100, 10; //
k = 1, x = 100, b = 10
; // Вызов
макроса
operationY;
; // Вызов
макроса
out Values$63, $64;
; // Холостая команда
nop;
; // Вызов макроса ldiRegister
ldiRegister 70, 2, 50; //
k = 70, x = 2, b = 50
; // Вызов
макроса
operationY;
; // Вызов
макроса
out Values$66, $67;
; // Холостая команда
nop;
; // Конец компиляции
.EXIT;
Результат
Вывод
В результате выполнения программы были получены
правильные значения, которые были рассчитаны предварительно «вручную»:
1. 0xFA = 250 = 0b11111010;
. 3. 0x5A
= 90 = 0b1011010.
Входные данные вводились с помощью определенного
макроса ldiRegister
с командой загрузки значений в регистры ldi.
Результаты вычислений сохранялись помощью макроса outValues
в ячейки ОЗУ с адресами $60, $63, $66 (младший б. результата), $61,
$64, $67 (старший б. результата) для соответственно.
Программа писалась в AVR
Studio
6.