Подпрограмма sqr. asm, текст которой приведен в Программе 8.3, базируется на подпрограмме из Программы 6.7 (стр. 186), выполняющей перемножение двух-байтных значений. В нашем случае при входе в подпрограмму содержимое рабочего регистра копируется в регистр с именем X, а в регистрах X_COPY_H:X_COPY_L формируется 16-битная копия этого значения. Используя алгоритм сдвига и сложения, вычисляется значение X х X = X2. Эти три регистра размещаются в секции TEMP с помощью директивы udata_ovr, которая сообщает компоновщику о том, что эти регистры могут повторно использоваться другими модулями. Из шар-файла можно увидеть, что переменная X была размещена в регистре h’50’, как и переменная I, использующаяся в подпрограмме SQR_ROOT (см. Программу 8.3). За счет этого достигается гораздо более эффективное использование памяти данных. Переменные, существующие только в пределах той подпрограммы, в которой они определены, в языке Си называются
include ”p16f627.inc"
; Подпрограмма SQR
; **********************
; * ФУНКЦИЯ: Возводит в квадрат 1-байтное число и возвращает 2-байтный результат *
; * ПРИМЕР: X = 10h (16), SQUARE = 0100h (256) *
; * ВХОД: X в W *
; * ВЫХОД: SQUARE:2 в области неинициализированных данных *
; **********************
BANK 0 udata; Статические данные
SQUARE res 2; Старший: младший байты квадрата
; -----------------------
TEMP udata_ovr; Автоматические данные
X res 1; X
X_COPY_L res 1 ; Копия X
X_COPY_H res 1; Старший байт X
; -----------------------
TEXT code
; Задача 1: Обнуляем 2-байтное значение квадрата
SQR clrf SQUARE
clrf SQUARE+1
; Задача 2: Копируем и расширяем X до 16 битов
movwf X; Сохраняем X в памяти данных
movwf X_COPY_L; Создаем копию X
clrf X_COPY_H; и расширяем до двух байтов
; Задача 3: ВЫПОЛНЯТЬ
; Задача 3а: Сдвигаем X на один бит вправо
SQR_LOOP bcf STATUS,С; Сбрасываем бит перекоса
rrf X,f; Сдвигаем
; Задача 3б: ЕСЛИ С == 1, ТО прибавить сдвинутое значение X к квадрату
btfss STATUS,С; ЕСЛИ С == 1, TO складываем
goto SQR_CONT; ИНАЧЕ пропускаем эту задачу
movf X_COPY_L,w; ВЫПОЛНЯЕМ сложение
addwf SQUARE+1,f; Сначала младшие байты
btfsc STATUS,С; ЕСЛИ нет переноса, ТО переходим к старшим байтам
incf SQUARE, f; ИНАЧЕ учитываем перенос
movf X_COPY_H,w; Теперь старшие байты
addwf SQUARE,f
; Задача 3 г: Сдвигаем 1б-битную копи» X на один бит вправо
SQR_CONT bcf STATUS,С; Сбрасываем бит переноса
X_COPY_L,f
X_COPY_H,f
; ПОКА X не равен нулю
movf X,f ; Проверяем множитель на ноль
btfss STATUS,Z
goto SQR_LOOP; ЕСЛИ не ноль, TO повторяем вычисления
FINI return; ИНАЧЕ ВЫХОДИМ
global SQUARE, SQR
end