Файл: Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 16.06.2025
Просмотров: 3616
Скачиваний: 3
Младший полубайт числа .08 равен .08. Младший полубайт числа .150 равен .06. Флаг DC сбросился потому, что .08+.06=.14 (меньше .15-ти).
Атеперь просуммируйте числа, например, .08 (00001000) и .153 (10011001). Флаг DC поднялся.
Почему?
Младший полубайт числа .08 равен .08. Младший полубайт числа .153 равен .09. Флаг DC поднялся потому, что .08+.09=.17 (больше .15-ти).
Авот пример, когда оба флага (C и DC) поднимаются.
Просуммируйте числа, например, .139 (10001011) и .157 (10011101). Флаги С и DC поднялись.
Почему?
Младший полубайт числа .139 равен .11. Младший полубайт числа .157 равен .13. Флаг DC поднялся потому, что .11+.13=.24 (больше .15-ти).
Флаг С поднялся потому, что .139+.157=.296 (больше .255-ти).
После исполнения команды addlw, в регистр W, будет записано число 28h (.40). Разбираемся, откуда оно "взялось".
Из-за того, что число .296 больше числа .255, произошел переход на второй "виток" счета.
Впределах этого второго "витка", результат суммирования "займет положение" числа
.296-.256=.40 (28h).
Количество этих "витков" не может быть более двух (почему? Ответьте самостоятельно). Таким образом, вне зависимости от значения суммы двух чисел, отображаемой байтом, флаг DC "реагирует" только на результаты выполнения операций сложения (вычитания) содержимого младших полубайтов.
Образно выражаясь, флагу DC "все-равно, что происходит" в старшем полубайте.
Он работает на своем "узком участке" в 4 бита и "контролирует" именно этот участок, а не весь байт.
Весь байт (оба полубайта) "контролируют" флаги Z и C.
Возникает вопрос: "Где может дислоцироваться этот легендарный байт, с которым мы все время работаем?"
Ответ: там, куда программист посчитает целесообразным его поместить.
Вданном случае, "местом его дислокации" является регистр W (см. комментарий к команде
ADDLW).
Если же применить байт-ориентированную команду ADDWF, то можно выбрать, куда поместить результат операции: или во всё тот же аккумулятор, или в регистр общего назначения, а это уже "выход на широкий, оперативный простор".
А теперь посмотрите в комментарий к флагу DC (см. распечатку).
Внем флаг DC называется флагом десятичного переноса - заёма.
Этот комментарий я, в свое время, взял из технической документации, предоставляемой компанией Microchip.
Флаг DC не "привязан" к десятичной системе исчисления, так как для того чтобы осуществить такую "привязку", нужно "привязать" перенос-заём не к числу .15, а к числу .9.
Этого нет.
Флаг DC "привязан" только к двоичной системе исчисления (так же, как и остальные флаги). Так что, слово "десятичного", из текста комментария к флагу DC лучше либо вообще убрать, либо заменить его на слово "полубайтного".
Флаг DC может применяться только для контроля типа "перенос - заем есть/нет" в "зоне" 4-хбитных чисел (.00 … .15 ).
Каким-то образом "аппаратно вычленить", из байта, младший полубайт и работать с ними отдельно, технически невозможно, так как все регистры ПИКов (по крайней мере, среднего семейства) 8-битные.
То, что "получается на выходе" - всегда 8-битное число.
Поэтому, при анализе "реакции" флага DC на результат соответствующей операции, приходится, из 8-битного результата, "вычленять" 4-хбитное число.
Только после этого можно ответить на вопрос: "Почему флаг DC поднялся или опустился?" Если же производятся операции с 8-битными числами из числового диапазона от .00 … .15 , то никаких проблем нет.
С учетом специфики флага DC, практическая надобность в его использовании, по сравнению с другими флагами, мала.
198
Если нужно "привязать" ход исполнения программы к событиям переносов/заёмов, то в подавляющем большинстве случаев, используется флаг С.
А теперь давайте остановимся, "переведем дух" и постараемся понять смысл прочитанного. Может возникнуть вопрос: "Зачем нужно было так подробно расписывать этот въедливый процесс? Дал бы готовые определения, и дело с концом."
Ответ: при таком подходе к работе, программист рискует оказаться один на один со множеством неразрешимых задач, которые он не сможет решить даже при сильнейшем желании это сделать.
Таких задач, по ходу составления и отладки программы, может быть много, и если не владеть эффективной и агрессивной методикой их решения (типа "я тебе покажу кузькину мать!" или "не хочешь отдавать? Возьму силой"), то участь этого программиста печальна.
Какой смысл "взращивать" в себе комплекс неполноценности по отношению, например, к тем же флагам C и DC, если пользуясь достаточно простыми методиками, и имея в своем распоряжении такой мощнейший "инструмент" как MPLAB, можно "выпотрошить/взломать" не только эти флаги, но и многое другое.
Спокойно и по-деловому. Без обманчивых надежд на "манну небесную".
Польза такого рода "взломов" не столько в том, что "добывается" информация, сколько в том, что она как бы "становится родной" и поэтому легко "уходит в подкорку".
Ввиде опыта и индивидуальных, для каждого программиста, образов, которые, в нужное время, "извлекаются" из подсознания в виде готового (или почти готового) решения, которое не нужно каждый раз "вымучивать" и "рожать при помощи кесарева сечения".
Для того чтобы такое "извлечение" происходило в "автомате", нужно основательно "попотеть" и "провести в симуляторе" много времени, производя при этом какие-то осознанные, целенаправленные действия, с "уходом" в заблуждения и "выкарабкиванием" из них. Примерно такого рода процесс я и попытался воспроизвести для затруднительной ситуации типа "как работают флаги C и DC?".
Это также можно рассматривать как примитивный пример программного анализа ("взлома"). Вывод: "не стоит ждать милостей от природы".
Если программист хочет добиться чего-то стОящего, то ему нужно не ждать "бесплатного сыра", а со знанием дела, "брать в руки интеллектуальную дубину и выбивать всю дурь из своих затруднений и проблем".
Нашему брату не нужно объяснять, как с ней обращаться. Лишь бы она была в наличии, да потяжелее.
Плюс хорошие мозги.
Вот так и рождаются классные программисты. Теперь, поближе к практике.
Вследующем разделе, будет приведен пример использования флага C.
"Самоучитель по программированию PIC контроллеров для начинающих" http://ikarab.narod.ru E-mail: karabea@lipetsk.ru
199
14. Пример задействования флага С в трехбайтном суммирующем устройстве. Циклический сдвиг. Операция умножения.
Пример реализации 3-байтного суммирующего устройства.
Составляя любую программу, программист работает с тем или иным количеством регистров общего назначения.
С их содержимым производятся различные операции.
Все они - однобайтные, и в пределах одного байта, работа с ними не вызывает особых затруднений.
Но часто возникает необходимость в работе с числами, значения которых велики (более, чем
.255).
Например, мой частотомер содержит 8 десятичных разрядов, что соответствует максимальному значению отображаемого, десятичного числа 99 999 999.
Вдвоичном виде, это число выглядит так: 101 11110101 11100000 11111111 (можете убедиться в этом в конверторе систем исчислений).
Итого, 27 двоичных разрядов.
Для того чтобы отобразить такое число, трех регистров окажется мало (8х3=24 разряда), следовательно, нужно задействовать 4 регистра общего назначения (8х4=32 разряда).
При этом получается "перебор" в 5 разрядов, но во-первых, "кашу маслом не испортишь" (эти 4 регистра способны отобразить число гораздо большее, чем 99999999), а во-вторых, выбора все-равно нет, так как все регистры 8-битные.
Вопрос: как распределить эти разряды по регистрам? Ответ: необходимо определить порядок старшинства. Вспоминайте о том, о чем говорилось ранее (HH, H, M, L).
Назначаем/"прописываем" регистры, например, с названиями RegHH, RegH, RegM, RegL и "закрепляем" за каждым из них по одному байту 4-байтного (32-битного) двоичного числа, начиная с младшего (он будет "лежать" в регистре RegL) и далее, в порядке возрастания старшинства, вплоть до самого старшего (он будет "лежать" в регистре RegHH).
Таким образом, мы распределили 4-байтное, двоичное число по 4-м регистрам общего назначения.
Таким образом, количество регистров, входящих в состав многобайтного регистра, назначается по принципу "перекрытия максимально возможного числа".
Вданном примере, нужно 27 разрядов, а организовано 32.
Это единственный вариант с минимально возможным "перебором".
Например, в случае применения линейки из семи 7-сегментных индикаторов, достаточно и трех регистров (RegH, RegM, RegL).
А теперь давайте осмыслим, что мы "сотворили".
Мы "раздробили" единое, 4-байтное число, на 4 части, нарушив тем самым внутренние связи, существующие между байтами.
Проще говоря, имеются 4 отдельных части, которые, если не принять каких-то мер, между собой взаимодействовать не будут.
Следовательно, нужно каким-то образом организовать это взаимодействие.
Необходимость этой организации можно объяснить на таком примере. Имеется какое-нибудь устройство на микросхеме 8-разрядного регистра (ИР). Требуется собрать то же самое, но на 2-х микросхемах 4-разрядных регистров.
Следовательно, нужно соответствующим образом соединить эти две микросхемы, ведь без такого соединения, устройство не будет работать так, как нужно.
Примерно то же самое нужно сделать и в нашем случае.
Разница заключается в том, что в одном случае, речь идет об аппаратном способе соединения, а в другом случае, о программном способе соединения.
Ради этого и затеивались "разборки" с флагами.
То есть, взаимодействие байтов, "внутри" многобайтного числа, можно организовать с помощью флагов.
То же самое, но "с другого бока": с помощью флагов, из нескольких регистров общего назначения, можно создавать N-байтные регистры (N - количество задействованных регистров общего назначения).
Специфика организации работы таких регистров состоит в том, что многобайтный регистр "рождается" только тогда, когда программа этого "захочет".
200
То есть, в том случае, когда организовано программное взаимодействие между соответствующими байтами.
Если это взаимодействие организовано, то несколько регистров общего назначения будут работать как один многобайтный регистр.
На примере "учебно-тренировочного", суммирующего устройства, файлы которого называются c_dc.asm и c_dc_1.asm ("иллюстрация" принципа), давайте разберемся, как с помощью программных средств, организуется трехбайтный регистр, и как он работает?
Файл программы, с формализованными комментариями, называется c_dc.asm
(находится в папке "Тексты программ").
Это выглядит так:
;********************************************************************************
;ПРИМЕР ИСПОЛЬЗОВАНИЯ ФЛАГА "C" (А ТАКЖЕ И ФЛАГА "Z")
;******************************************************************************** ; c_dc.asm Стандартная подпрограмма суммирования двух трехбайтных чисел
;******************************************************************************** RegH, RegM, RegL - трехбайтное число 1-го слагаемого.
TimerH, TimerM, TimerL - трехбайтное число 2-го слагаемого.
Результат суммирования сохраняется в регистрах TimerH, TimerM, TimerL.
;********************************************************************************
; |
"ШАПКА ПРОГРАММЫ" |
;================================================================================ ;.............................................................
;.............................................................
;================================================================================
; Определение положения регистров специального назначения.
;================================================================================
Status equ 03h ; Регистр Status.
;.............................................................
;.............................................................
;================================================================================
; Определение названия и положения регистров общего назначения.
;================================================================================
RegL |
equ |
0Ch |
; Регистр младшего разряда 1-го слагаемого. |
RegM |
equ |
0Dh |
; Регистр среднего разряда 1-го слагаемого. |
RegH |
equ |
0Eh |
; Регистр старшего разряда 1-го слагаемого. |
TimerL |
equ |
1Ch |
; Регистр младшего разряда 2-го слагаемого. |
TimerM |
equ |
1Dh |
; Регистр среднего разряда 2-го слагаемого. |
TimerH |
equ |
1Eh |
; Регистр старшего разряда 2-го слагаемого. |
;............................................................. |
|||
;............................................................. |
;================================================================================
; Определение места размещения результатов операций.
;================================================================================
W |
equ |
0 |
; |
Результат |
направить |
в |
аккумулятор. |
F |
equ |
1 |
; |
Результат |
направить |
в |
регистр. |
; |
............................................................. |
;================================================================================
; Присваивание битам названий.
;================================================================================
C |
equ |
0 |
; |
Бит |
флага |
переноса-заёма. |
Z |
equ |
2 |
; |
Бит |
флага |
нулевого результата. |
;.............................................................
;================================================================================
org |
0 |
; |
Начать выполнение программы |
goto |
START |
; |
с подпрограммы START. |
;********************************************************************************
;******************************************************************************** ; РАБОЧАЯ ЧАСТЬ ПРОГРАММЫ
201