Файл: Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 16.06.2025

Просмотров: 3593

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

;================================================================================

; Определение места размещения результатов операций.

;================================================================================

W

equ

0

;

Результат

направить

в

аккумулятор.

F

equ

1

;

Результат

направить

в

регистр.

;.............................................................

;================================================================================

; Присваивание битам названий.

;================================================================================

C equ 0 ; Бит флага переноса-заёма.

;.............................................................

;================================================================================

org

0

;

Начать выполнение программы

goto

START

;

с подпрограммы START.

;********************************************************************************

;********************************************************************************

; РАБОЧАЯ ЧАСТЬ ПРОГРАММЫ

;********************************************************************************

START ......................................

......................................

......................................

......................................

На момент начала ПП умножения, в регистр RegL должно быть записано однобайтное

двоичное число (множимое), которое нужно умножить на 10 (множитель).

Значения произведений отражаются в двухбайтном регистре RegL/RegH.

;================================================================================

;Подпрограмма умножения на 10 однобайтных двоичных чисел (.00 ... .255)

;================================================================================

;Подготовительные операции.

;--------------------------------------------------------------------------------

bcf

Status,C

; Установка в

0 бита № 0 регистра Status.

movf

RegL,W

; Копирование

содержимого регистра RegL

; в регистр W.

clrf

RegH

; Сброс в 0 содержимого регистра RegH.

;--------------------------------------------------------------------------------

; Три последовательных умножения на 2 (умножение на 8).

;--------------------------------------------------------------------------------

rlf

RegL,F

; Циклический

сдвиг влево содержимого

; регистра RegL с сохранением результата

; в нем же.

btfsc

Status,C

; Опрос состояния бита флага С.

rlf

RegH,F

; Если С=1, то циклический

сдвиг влево

; содержимого

регистра RegH c переносом в его

; младший разряд 1 из бита

флага С, с

; сохранением

результата в

нем же (в RegH).

;--------------------------------------------------------------------------------

rlf

RegL,F

; Если С=0 (а

также после исполнения

; предшествующей команды),

то циклический

; сдвиг влево

содержимого регистра RegL с

; сохранением

результата в

нем же.

btfsc

Status,C

; Опрос состояния бита флага С.

rlf

RegH,F

; Если С=1, то циклический

сдвиг влево

; содержимого

регистра RegH с переносом в его

; младший разряд 1 из бита

флага С, с

; сохранением

результата в

нем же (в RegH).

;--------------------------------------------------------------------------------

rlf

RegL,F

; Если С=0 (а

также после исполнения

; предшествующей команды),

то циклический

; сдвиг влево

содержимого регистра RegL, с

; сохранением

результата в

нем же.

btfsc

Status,C

; Опрос состояния бита флага С.

rlf

RegH,F

; Если С=1, то циклический

сдвиг влево

; содержимого

регистра RegH с переносом в его

; младший разряд 1 из бита

флага С, с

211


;сохранением результата в нем же RegH).

;Если С=0 (а также после исполнения

;предшествующей команды), то программа

;исполняется далее (переход к суммированиям)

;--------------------------------------------------------------------------------

;2 последовательных суммирования сохраненного в регистре W множимого, к

;результату умножения множимого на 8.

;--------------------------------------------------------------------------------

addwf

RegL,F

; Сложить содержимое регистров RegL и W с

; сохранением результата в регистре RegL.

btfsc

Status,C

; Опрос состояния бита флага С.

incf

RegH,F

; Если бит С=1, то инкремент содержимого

; регистра RegH с сохранением результата

; в нем же.

addwf

RegL,F

; Если бит С=0 (а также после исполнения

; предшествующей команды), то сложить

; содержимое регистров RegL и W, с

; сохранением результата в регистре RegL.

btfsc

Status,C

; Опрос состояния бита флага С.

incf

RegH,F

; Если бит С=1, то инкремент содержимого

; регистра RegH, с сохранением результата

; в нем же.

;--------------------------------------------------------------------------------

........................

; Если бит С=0 (а также после исполнения

........................

; предшествующей команды), то программа

; исполняется далее.

......................................

......................................

;********************************************************************************

end ; Конец программы.

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

В этом случае, после команды последнего инкремента, должна быть исполнена команда call или goto соответственно.

Файл программы умножения на 10, с неформализованными комментариями,

называется Rlf_1.asm (находится в папке "Тексты программ").

Она выглядит так:

;********************************************************************************

;ПРИМЕР ИСПОЛЬЗОВАНИЯ ФЛАГА "C" В ОПЕРАЦИИ УМНОЖЕНИЯ НА 10

;********************************************************************************

; Rlf_1.asm Подпрограмма умножения 8-битных чисел на 10

;********************************************************************************

......................................

......................................

......................................

;================================================================================

;Подпрограмма умножения на 10 однобайтных двоичных чисел (.00 ... .255)

;================================================================================

;Подготовительные операции.

;--------------------------------------------------------------------------------

bcf

Status,C

; Предварительный сброс флага С.

movf

RegL,W

; Копирование содержимого регистра RegL

; в регистр W.

clrf

RegH

; Предварительный сброс содержимого

; регистра RegH.

;--------------------------------------------------------------------------------

; Три последовательных умножения на 2 (умножение на 8).

;--------------------------------------------------------------------------------

rlf

RegL,F

; Умножение на 2 числа, записанного в

; регистре RegL, с сохранением результата

212


; в нем же.

btfsc

Status,C

; Флаг С поднят или опущен

?

rlf

RegH,F

; Если поднят, то циклический сдвиг влево

; содержимого

регистра RegH с переносом в его

; младший разряд 1 из бита

флага С, с

; сохранением

результата в

нем же (в RegH).

;--------------------------------------------------------------------------------

rlf

RegL,F

; Если опущен

(а также после исполнения

; предшествующей команды),

то умножение на 2

; числа, записанного в регистре RegL, с

; сохранением

результата в

нем же.

btfsc

Status,C

; Флаг С поднят или опущен

?

rlf

RegH,F

; Если поднят, то циклический сдвиг влево

; содержимого

регистра RegH, с переносом в

; его младший

разряд 1 из бита флага С, с

; сохранением

результата в

нем же (в RegH).

;--------------------------------------------------------------------------------

rlf

RegL,F

; Если опущен

(а также после исполнения

;предшествующей команды), то умножение на 2

;числа, записанного в регистре RegL, с

;сохранением результата в нем же.

btfsc

Status,C

; Флаг С поднят или опущен

?

rlf

RegH,F

; Если поднят, то циклический сдвиг влево

; содержимого

регистра

RegH,

с

переносом в

; его младший

разряд 1

из бита

флага С, с

; сохранением

результата в

нем

же (в RegH).

; Если опущен

(а также

после

исполнения

; предшествующей команды),

то программа

; исполняется

далее (переход

к

суммированиям)

;--------------------------------------------------------------------------------

;2 последовательных суммирования сохраненного в регистре W множимого к

;результату умножения множимого на 8.

;--------------------------------------------------------------------------------

addwf

RegL,F

; Сложить результат умножения на 8 и множимое

; (сохраненное в регистре W), с сохранением

; результата в регистре RegL.

btfsc

Status,C

; Флаг С поднят или опущен?

incf

RegH,F

; Если флаг С поднят, то инкремент

; содержимого регистра RegH, с сохранением

; результата в нем же.

addwf

RegL,F

; Если флаг С опущен (а также после

; исполнения предшествующей команды), то

; сложить результат предшествующего

; суммирования и множимое, с сохранением

; результата в регистре RegL.

btfsc

Status,C

; Флаг С поднят или опущен?

incf

RegH,F

; Если флаг С поднят, то инкремент

; содержимого регистра RegH, с сохранением

; результата в нем же.

;--------------------------------------------------------------------------------

........................; Если флаг С опущен (а также после

........................; исполнения предшествующей команды), то ; программа исполняется далее.

......................................

......................................

;******************************************************************************** end ; Конец программы.

Всвое время, когда я разбирался с умножением, мне нужно было выбрать: или найти готовую ПП умножения, или составить ее самому.

Я выбрал последнее. Так "родилось сие творение".

И дело даже не в том, что наиболее вероятным результатом подобного рода работы является "изобретение колеса", а в том что после нее, наступает сильнейшее "просветление", и приобретается ценный опыт.

Вконечном итоге, такой "въедливый" и достаточно трудоемкий (на первых порах) стиль

213


"разборок с непонятностями", оказывается гораздо эффективнее, чем достаточно "мутный и ограниченный" стиль работы, связанный с поиском чего-то готового.

При этом, частенько, программист не вдается в детали того, что он находит.

По этой причине, велика вероятность возникновения затруднительных ситуаций. Вплоть до "тупиков".

На мой взгляд, критерием успешности является что-то типа этого: "Зачем искать готовую, нужную программу/подпрограмму? Проще, быстрее и качественнее составить ее самому." Итак, предположим, что нужно составить подпрограмму умножения.

Наиболее сложный "участок уже пройден". Простейший принцип умножения сформулирован. Ну и в чем дело? Как говорится, "вперед и с песней"!

Конструируем подпрограмму умножения однобайтного двоичного числа на 10.

Определяемся с регистрами общего назначения.

Так как множимое является числом, отображаемым одним байтом (.00 ... .255), то такое множимое может быть записано в один регистр общего назначения.

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

Таким образом, максимальное значение произведения не может превысить числа

255х10=.2550

То есть, для отображения такого числа, одного регистра общего назначения мало и необходимо назначить еще один регистр общего назначения.

И в самом деле, двухбайтный регистр способен отобразить число от 0 до 256х256=65536-1=.65535, и число .2550 попадает в этот числовой диапазон.

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

Под младший байт произведения (он же - байт множимого), "прописываем" регистр общего назначения с названием, например, RegL.

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

Под старший байт произведения, "прописываем" регистр общего назначения с названием, например, RegH.

Вэтот байт, в ходе последовательных процедур умножения на 2, будут осуществляться переносы.

Теперь нужно определиться с начальными условиями.

Для этого нужно ответить на вопрос: "Какие числа должны быть записаны в регистры RegL, RegH и в бит флага С на момент начала исполнения первого, циклического сдвига?" Ответ: в регистр RegL будет записываться число множимого.

Байт регистра RegH нужно сбросить в 0 (clrf RegH).

Впротивном случае, это равносильно наличию переносов, которых не было, что неприемлемо (увеличенное, по сравнению с истинным, значение произведения). Бит флага С нужно сбросить в 0 (bcf Status,C).

Впротивном случае, результат умножения будет не верен.

Посмотрите в текст программы.

В"подготовительных операциях", Вы увидите обе этих команды.

В"шапке" программы, Вы увидите, что регистры RegL, RegH, а также и регистр Status, "введены в эксплуатацию" ("прописаны").

Исходя из сформулированных выше условий, ПП умножения должна содержать не только группы команд умножения на 2, но и группы команд суммирования, причем, одним из слагаемых обязательно должно быть множимое, и операции сложения должны исполняться после завершения операции умножения на 8 (3-х операций умножения на 2). Следовательно, в "подготовительных операциях" нужно сохранить множимое в каком-то регистре.

Под это дело, можно "прописать" еще один (третий) регистр общего назначения, а можно и скопировать множимое в регистр W, так как он, при исполнении процедур умножения на 2, не задействуется.

Поэтому, необходимости в увеличении количества задействованных регистров общего назначения, нет.

Вполне можно обойтись и двумя.

Следовательно, с целью дальнейшего использования множимого в группах команд

214


суммирования, в "подготовительных операциях", с помощью команды movf RegL,W, нужно сохранить множимое в регистре W.

Итак, группа команд "подготовительных операций" сформирована. Порядок их расположения, в этой группе, не имеет значения.

Можно "перетасовать их, как карты". Это не отразится на результате работы подпрограммы, так как все 3 команды "развязаны" относительно друг друга.

Теперь можно заняться "конструированием" группы команд умножения на 2.

Возникает вопрос: "Какие именно команды должны входить в группу команд умножения на 2 и в каком порядке, в пределах этой группы, они должны располагаться?"

Исходя из сказанного ранее, однозначным является то, что первой должна следовать команда циклического сдвига влево rlf RegL,F, а второй, команда опроса бита флага С (btfsc Status,C), а также и то, что перенос, в случае его наличия, должен осуществляться в младший разряд старшего байта (в регистр RegH).

Что дальше? Каким образом должно происходить "взаимодействие" младшего и старшего байтов при переносах?

На момент начала первого циклического сдвига влево, в регистре RegH установлен 0, и в дальнейшем, от переноса к переносу, значения чисел, "лежащих" в регистре RegH, должны только увеличиваться.

Вопрос: "По какому закону?"

Могут быть следующие варианты: суммирование, инкремент, циклический сдвиг влево. Суммирование отпадает, так как в этом случае, задача, в конечном итоге, сводится к "привязке" к нескольким значениям констант, практически реализовать которую очень затруднительно.

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

Чтобы проверить правильность этого высказывания, давайте немного "погоняем нули с единицами на бумаге".

Умножим, например, число .194 (11000010) на 8 (2х2х2), применив, для переносов в старший байт, команды инкремента.

194 00000000 11000010 ; множимое, в бите С - ноль.

388 00000001 10000100 ; в бит С "пришла" 1 из старшего бита младшего байта, следовательно, инкремент старшего байта.

52100000010 00001001 ; из бита С "ушла" 1 в младший бит младшего байта,

вбит С "пришла" 1 из старшего бита младшего байта,

следовательно, инкремент старшего байта.

53100000010 00010011 ; из бита С "ушла" 1 в младший бит младшего байта,

вбит С "пришел" 0 из старшего бита младшего байта, следовательно, инкремента старшего байта нет.

В идеале, должен получиться результат 194х8=.1552, а получилось .531.

Вывод: при организации умножения посредством последовательных, "многоступенчатых" процедур умножения на 2, операции инкремента, для организации переносов в старший байт, применять нельзя.

Проанализировав результат (нужно .1552, а получилось .531), можно прийти к выводу, что при формировании нескольких переносов, наращивание значений чисел, формируемых в регистре RegH, должно происходить значительно бОльшими "темпами", чем в случае применения операций инкремента.

Исходя из этого, на "роль палочки - выручалочки претендует" все та же операция циклического сдвига влево, только применяемая по отношению к содержимому старшего байта.

И в самом деле, она эквивалентна операции умножения на 2, что обеспечивает более высокие "темпы прироста", чем при применении операции инкремента.

Таким образом и "родилась" группа команд умножения на 2, которые можно последовательно ("цепочкой") соединять между собой.

Посмотрите в текст программы.

Вы видите "цепочку" из трех групп команд умножения на 2 (умножение на 8).

Может возникнуть вопрос: "Как два байта делят между собой один бит флага С, ведь они оба работают с ним?"

А так и работают - по очереди.

215