; Глобальные объявления
include "p16f84a.inc"; Заголовочный файл
cblock h’26’; Начало блока переменных (с регистра h’26’)
NUM:2; Старший байт (NUM), младший байт (NUM+1)
endc; Конец блока
; Основной цикл -------------
MAIN call SQR_ROOT; Фиктивный основной цикл
sleep; Останавливаемся
; --------------------------------
; ********************************
; * ФУНКЦИЯ: Вычисляет корень квадратный из 16-битного целого *
; * ПРИМЕР: Число = h’FFFF’ (65,535), Корень = h’FF’ (d’255’)*
; * ВХОД: Число в регистрах NUM: NUM+1 *
; * ВЫХОД: Корень в W. Регистры NUM: NUM+1 и I:I+1, COUNT изменяются *
; *********************************
; Локальные объявления
cblock;
I:2, COUNT:1; Магическое число и счетчик цикла
endc
org h’200’; Код размещается в памяти программ начиная с h’200’
SQR_ROOT clrf COUNT; Задача 1: Обнулить счетчик цикла
clrf I; Задача 2: Инициализация магического числа единицей
clrf I+1;
incf I+1,f;
; Задача 3: ВЫПОЛНЯТЬ
SQR_LOOP movf I+1,w; Задача 3а: Number — I
subwf NUM+1,f; Вычитаем из младшего байта исходного числа
movf I,w; Берем старший байт магического числа
btfss STATUS,С; ЕСЛИ не было заема (С==1), ТО пропускаем
addlw 1; Учитываем заем
subwf NUM,f; Вычитаем старшие байты
; Задача 3б: ЕСЛИ потеря значимости, ТО выйти
btf ss STATUS,С; ЕСЛИ нет заема (C==1), TO продолжаем
goto SQR_END; ИНАЧЕ вычисление завершено
incf COUNT,f; Задача 3в: ИНАЧЕ инкрементируем счетчик цикла
movf 1 + 1,w; Задача 3 г: Увеличиваем магическое число на 2
addlw 2
btfsc STATUS,С; Если нет переноса, ТО пропускаем
incf I,f; ИНАЧЕ корректируем старший байт
movwf I+1
goto SQR_LOOP
SQR_END movf COUNT,w; Задача 4: Возвращаем счетчик цикла в качестве значения корня
return
end
Директива equ используется также для присваивания имен переменным, хранимым в РОН. Так, в Программе 6.12 на стр. 199 имеются следующие строки:
NUM_H equ h’26’; Исходное значение, старший байт
NUM_L equ h’27’; Исходное значение, младший байт
Эти имена и адреса должны быть, разумеется, уникальными для данной программы, а не для какого-то конкретного устройства. В Программе 8.1 используется пара директив cblock — endc, выполняющих схожие функции. Эти директивы сообщают ассемблеру о том, что переменные должны быть размещены в указанных регистрах. В строках, заключенных между данными директивами, перечисляются имена переменных и количество байтов, занимаемых каждой переменной. Возвращаясь к нашему примеру:
cblock h’26’; Начало блока переменных (с регистра h’26’)
NUM:2; Резервируем два байта под NUM
endc; Конец блока
где число, записанное через двоеточие после имени переменной, определяет количество байтов, зарезервированных подданную переменную. Отдельные байты, входящие в состав переменной, можно адресовать с использованием арифметического оператора «+»; например, в 3-байтной переменной SUM:3 1-й байт обозначается как SUM, 2-й байт — как SUM+1 и 3-й байт — как SUM+2.