Вы находитесь на странице: 1из 19

5/11/1.

Развитие темы: вариант подпрограммы преобразования 2-байтных


двоичных чисел в 4-разрядные десятичные числа от Сергея Рослика.

Опять же, как это часто в жизни бывает, если имеет место быть “скелет”, то на него,
“по закону жанра”, “автоматически” начинает “наращиваться мясо”.
Именно по этому принципу и создаются те “навороты”, в которые, если не знать,
откуда “ноги растут” (а они всегда растут из одного места. В противном случае
получается черт знает что), можно “въезжать” долго и упорно, а можно и вообще “не
въехать”.
Таким образом, то, что Вы прочтете ниже, вполне закономерно, естественно и
нормально. Так и должно быть.
Информация от Сергея Рослика выделена темно – синим цветом.

Подпрограмма преобразования двоичного кода в двоично-десятичный, методом


“разности”.

Принцип программы построен на вычитании из десятичного числа разрядов 1000, 100, 10


и вычислении остатка.
Например, необходимо преобразовать число 4786, находящееся в двухбайтном регистре
(BH и BL), в двоично-десятичный код, для последующего вывода его на индикацию.
Программа выбирает из таблицы констант число 1000 (в таблице представлены инверсные
значения для операций разности), после чего начинает отнимать от 4786 число 1000.
4786-1000=3786
Значит, регистр LED3 необходимо инкрементировать
LED3=0+1=1
После этого проверяем, делимое больше делителя или нет?
Если больше, то производим ещё одну операцию вычитания
3786-1000=2786
Значит, регистр LED3 необходимо инкрементировать
LED3=1+1=2
И так далее, то есть,
2786-1000=1786, LED3=2+1=3
1786-1000=786, LED3=3+1=4
По технологии программы, выполняется ещё один дополнительный инкремент (LED3=5), но
после выравнивающих действий (декремент), в регистре LED3 (самый старший десятичный
разряд) остаётся лежать двоично-десятичное число 4 (5-1=4).
После этого, программа выбирает из таблицы констант 100 (-100), и по такому же принципу
(см. выше), начинает отнимать 100 из оставшегося числа 786.
Вследствие этого, содержимое регистра LED2 инкрементируется 7 раз, и в нём “осядет”
число 7, т.к. от числа 786 можно отнять число 100 только 7 раз (с учетом выравнивания или
балансировки. Это кому как нравится).
Итак, в 2-х старших, десятичных разрядах, “осело” число 47, а в остатке – число 86.
Опять, из таблицы выбираем константу 10 (-10) и производим операцию вычитания
86-10=76
И так далее (с учетом выравнивания).
Когда отнимать будет нечего, в регистре LED1 “осядет” число 8.
После этого, останется только заполнить регистр LED0.
После всех перечисленных выше операций, в регистре BL будет лежать число 6.
Здесь уже ничего преобразовывать не нужно.
Просто “переправляем” это число, через аккумулятор (W) в регистр LED0.
На этом преобразование заканчивается, и программа исполняется далее.
Итог:
- в регистре LED3 “осело” число 4,
- в регистре LED2 “осело” число 7,
- в регистре LED1 “осело” число 8,
- в регистре LED0 “осело” число 6,
что и требовалось.

1
Эту ПП в основном целесообразно использовать тогда, когда необходимо отобразить
десятичные числа в 1, 2, 3, 4 разрядах индикации.
Можно добавить и пятый разряд, но в нём максимально, что может отразиться, так это только
числа до 6 включительно (при двухбайтных данных), т.к. в два байта помещается только
числа до 65536.
Конечно, можно и увеличить число байт данных, но тогда увеличится и количество команд в
подпрограмме, и она, по этому показателю, будет проигрывать стандартной подпрограмме
BIN2_DEC.

2
;********************************************************************************
; BIN2_4.asm ПП преобразования двоичного кода в двоично-десятичный
; Используется м/контроллер PIC16F873. Частота кварца 4 Мгц.
; Автор: Рослик Сергей Львович.
;================================================================================
LIST p=16f873
__CONFIG 3731H
;================================================================================
; Определение положения регистров специального назначения.
;================================================================================
IndF equ 00h ; Доступ к памяти через FSR
PC equ 02h ; Счетчик команд.
Status equ 03h ; Регистр Status.
FSR equ 04h ; Регистр косвенной адресации.
;================================================================================
; Определение битов регистров.
;================================================================================
C equ 0 ; Бит регистра статус.
F equ 1
;********************************************************************************
;Назначение регистров общего назначения.
;********************************************************************************
BL equ 20h ; Младший регистр перекодируемого числа.
BM equ 21h ; Средний регистр перекодируемого числа.
LED0 equ 22h ; Разряд 1.
LED1 equ 23h ; Разряд 10.
LED2 equ 24h ; Разряд 100.
LED3 equ 25h ; Разряд 1000.
Count equ 26h ;
;********************************************************************************
org 0
goto START
;================================================================================
; Таблица констант для вычисления разности.
;================================================================================
CONST addwf PC,F
dt .24, .252, .232, .3, .156, .255, .100, .0, .246, .255, .10, .0
;================================================================================
; Начало выполнения подпрограммы.
;================================================================================
START movlw 1Dh ; Загрузка двоичного двухбайтного числа,
movwf BM ; которое необходимо преобразовать в
movlw 7Eh ; двоично-десятичный код.
movwf BL ;
;================================================================================
; Преобразование двухбайтного двоичного числа в четырехзначное десятичное число.
;================================================================================
BIN2_10 clrf LED0 ; Подготавливаем регистры для загрузки в
clrf LED1 ; них результатов двоично-десятичного
clrf LED2 ; преобразования.
clrf LED3 ;
clrf Count ; Счётчик манипуляции константами.
movlw LED3 ; Стандартная процедура косвенной адресации с
movwf FSR ; "переправкой" содержимого регистра,
movf IndF,W ; сначала, LED3, а затем и всех остальных
; регистров LED2, LED1, LED0.
NEXT movf Count,W ; Подготовка к вычисляемому переходу и выбора
call CONST ; констатнты вычитаемого из регистра BL.
addwf BL,F ; Операция разности с регистром BL.
btfsc Status,C ; Проверям, перенос был или нет.
incf BM,F ; Перенос был, BM+1.
movf Count,W ; Переноса не было.
addlw 1 ; Подготовка к вычисляемому переходу.

3
call CONST ; Выбераем вычитаемое для регистра BM.
addwf BM,F ; Операция разности с регистром BM.
incf IndF,F ; Подсчёт кол-ва делений числа, с переносом
; в LED.
btfsc Status,C ; Проверям, перенос был или нет.
goto NEXT ; Перенос был.
bsf Count,1 ; Инкремент счётчика на 2. :)
movf Count,W ; Подготовка к вычисляемому переходу.
call CONST ; констатнта слагаемого для регистра BL.
addwf BL,F ; Операция суммирования аккумулятора с
; регистром BL.
btfsc Status,C ; Проверям, перенос был или нет.
incf BM,F ; Перенос был BM+1.
movf Count,W ; Переноса не было.
addlw 1 ; Подготовка к вычисляемому переходу.
call CONST ; Константа слагаемого для регистра BM
addwf BM,F ; Операция суммирования аккумулятора с
; регистром BM.
decf IndF,F ; Декремент текущего LEDа, в регистре
; косвенной адресации.
decf FSR,F ; Загрузка следуещего регистра LED.

incf Count,F ; Настройка для выбора необходимой константы.


incf Count,F ;
movf Count,W ;

sublw .11 ; Проверка, константы все перебрали или нет?


btfsc Status,1
goto NEXT ; Если нет, то на новый круг, для следующего
; регистра LED.
movf BL,w ; Загружаем остаток в регистр результата
movwf LED0 ; преобразования единиц.

goto START ; Можно поставить точку останова.


;============================================================================
end

Проверяю работу программы в MPLAB.


Работает.
Включаю свой “сканер”.
Стратегия - в полном порядке.
В тактике, есть незначительные “пупырышки” (на суть не влияют).
1. Зачем, в подготовительных операциях, задействовать лишнюю команду на сброс
LED0?
Это регистр самого младшего десятичного разряда, в который единоразово, “по верху”,
записывается остаток от деления (я об этом говорил в предыдущем разделе), и не
важно, что в нем “лежит на подлете” к этой записи.
2. Зачем, после записи в FSR адреса регистра LED3, нужна команда movf IndF,W,
ведь следующая команда уничтожает содержимое регистра W путем пересылки в него
содержимого регистра Count (movf Count,W) ?
К тому же, ниже, обращение к регистру IndF есть (и уже по делу).
Команда movf IndF,W является просто лишней.
3. Имеются 2 пары команд movf Count,W и addlw 1, каждую из которых можно
заменить на одну команду incf Count,W.
Итог: 6 команд убыло, 2 команды прибыло. Выигрыш в 4 команды.
Мелочь, а душу радует.
Проверяю результат “зачистки”.
Программа работает.
Таким образом, программа приобретает следующий вид:

;********************************************************************************
; BIN2_4.asm Программа, демонстрирующая работу ПП преобразования двоичного
; кода в двоично-десятичный.

4
; Используется м/контроллер PIC16F873. Частота кварца 4 Мгц.
; Автор: Рослик Сергей Львович.
;********************************************************************************
; На входе: 2-байтное двоичное число (в 2-байтном регистре BL/BM).
; На выходе: 4-разрядное десятичное число (в младших полубайтах регистров
; LED3...LED0).
;********************************************************************************
LIST p=16f873 ; Используется PIC16F873.
__CONFIG 3731H
;================================================================================
; Определение положения регистров специального назначения.
;================================================================================
IndF equ 00h ; Доступ к памяти через FSR.
PC equ 02h ; Счетчик команд.
Status equ 03h ; Регистр Status.
FSR equ 04h ; Регистр косвенной адресации.
;================================================================================
; Присваивание названий биту и месту размещения результатов операций.
;================================================================================
C equ 0 ; Флаг переноса-заема.
F equ 1 ; Результат направить в регистр.
;================================================================================
; "Прописка" регистров общего назначения.
;================================================================================
BL equ 20h ; Младший регистр перекодируемого числа.
BM equ 21h ; Средний регистр перекодируемого числа.
LED0 equ 22h ; Разряд 1.
LED1 equ 23h ; Разряд 10.
LED2 equ 24h ; Разряд 100.
LED3 equ 25h ; Разряд 1000.
Count equ 26h ; Счетчик выбора констант из таблицы.
;================================================================================
org 0 ; Начать выполнение
goto START ; программы с ПП START.
;********************************************************************************

;================================================================================
; Таблица констант делителей (табличный вычисляемый переход).
;
================================================================================C
ONST addwf PC,F ; Приращение PC на величину содержимого W.
dt .24, .252, .232, .3, .156, .255, .100, .0, .246, .255, .10, .0
;================================================================================

;********************************************************************************
; НАЧАЛО ВЫПОЛНЕНИЯ ПРОГРАММЫ.
;********************************************************************************
; По умолчанию, используется число 1D7Eh (.7550), но может быть "заложено" и
; другое число.
;--------------------------------------------------------------------------------
START movlw 1Dh ; Загрузка в BM/BL двоичного двухбайтного
movwf BM ; числа, которое будет переведено
movlw 7Eh ; в двоично-десятичную форму.
movwf BL ;
;==============================================================================
; ПП преобразования двухбайтного двоичного числа в 4-разрядное десятичное число.
;==============================================================================
; Подготовительные операции.
;----------------------------------------
BIN2_10 clrf LED1 ; Подготовка к работе
clrf LED2 ; регистров результата
clrf LED3 ; 2/10 преобразования.
clrf Count ; Подготовка к работе счётчика выбора
; констант.
movlw LED3 ; Начало процедуры косвенной адресации:
movwf FSR ; запись в FSR адреса регистра LED3.
5
;================================================================================
; ПП формирования десятичного значения текущего LED с "привязкой" к конкретному
; делителю (константам).
; Деление происходит путем последовательного вычитания делителя из делимого, с
; подсчетом количества этих вычитаний ("оседает" в текущем LED), до момента,
; когда делитель становится больше делимого.
;================================================================================
NEXT movf Count,W ; Подготовка к выбору константы
; (то есть, к выбору делителя).
call CONST ; Выбор константы для регистра BL.
;----> Возврат по стеку из ПП CONST.
addwf BL,F ; BL-CONST=... (вычитание делителя из
; делимого в приложении к BL).
btfsc Status,C ; Перенос был или нет?
incf BM,F ; Если был, то BM+1=... (перенос в BM)
; Результат - в BM.
incf Count,W ; Если не было (а также после BM+1), то
; подготовка к выбору следующей константы.
call CONST ; Выбор константы для регистра BM.
;----> Возврат по стеку из ПП CONST.
addwf BM,F ; BM-CONST=... (вычитание делителя из
; делимого в приложении к BM).
incf IndF,F ; Подсчёт кол-ва вычитаний
;(текущий LED+1 =... Результат - в LED).
btfsc Status,C ; Перенос был или нет (делимое больше или
; меньше делителя)?
goto NEXT ; Если был (делимое больше делителя), то
; продолжаем вычитать.
;================================================================================
; Работа с остатком от деления.
;================================================================================
bsf Count,1 ; Если не был, то подготовка к выбору
movf Count,W ; константы (с адресом PC+02h) для
; формирования истинного значения остатка.
call CONST ; Выбор константы для регистра BL.
;----> Возврат по стеку из ПП CONST.
;-----------------------------------------
; Формирование истинного значения остатка.
;-----------------------------------------
addwf BL,F ; Операция суммирования содержимого W и BL.
btfsc Status,C ; Перенос был или нет?
incf BM,F ; Если был, то BM+1=... (перенос в BM)
; Результат - в BM.
incf Count,W ; Если не было (а также после BM+1),
; то подготовка к выбору константы.
call CONST ; Выбор константы для регистра BM.
;----> Возврат по стеку из ПП CONST.
addwf BM,F ; Операция суммирования содержимого W и BM.
decf IndF,F ; Устранение "перебора" в текущем LED.
;********************************************************************************
; Работа с текущей четверкой констант закончена
; (содержимое текущего LED сформировано).
;********************************************************************************

;================================================================================
; Переход на следующий LED и следующий, "привязанный" к нему, делитель.
;================================================================================
decf FSR,F ; Загрузка в FSR адреса следующего
; регистра LED.
incf Count,F ; Настройка для выбора необходимой константы
incf Count,F ; (для перехода на следующий делитель):
; Count+2=... Результат - в Count.
movf Count,W ; Count ---> W.
sublw .11 ; Проверка: все константы (делители)
btfsc Status,C ; перебрали или нет?
goto NEXT ; Если не все, то начинается работа со
6
; следующим LEDом и с "привязанной" к нему
; группой констант.
; Если все, то работаем с остатком от
; комплексного деления.
;================================================================================
; Работа с остатком от комплексного деления (окончание процедуры).
;================================================================================
movf BL,W ; Загружаем остаток в регистр
movwf LED0 ; десятичного разряда единиц.

goto START ; На этой команде можно поставить точку


; остановки.
;================================================================================
end ; Конец программы.

Работа программы

Математический принцип работы программы описан в письме Сергея и добавить мне к


этому нечего.
“Падаю” на тактику.
Прежде всего, нужно разобраться с константами.
Их 12 штук и они сгруппированы в 3 группы по 4 константы в каждой.
3 группы это 3 делителя: на 1000, на 100 и на 10.
Для остатка от этого последовательного, комплексного деления, константы не нужны.
Почему в группах по 4 константы?
Потому, что производятся операции с 2-байтным регистром.
Это первое.
Второе: вспомните (см. предыдущий подраздел), что, после осуществления процедуры
деления, остаток от деления не есть истинный остаток от деления.
Для того чтобы получить истинный остаток от деления, нужно сложить не истинный
остаток от деления (извиняюсь за такой пассаж, но так более понятно) с делителем.
Вот и получается, что для каждого из трех делителей нужно иметь по 4 константы:
- 2 константы байтов делителя в инвертированном виде и
- 2 константы байтов делителя в не инвертированном виде.
Первые 2 константы нужны для обеспечения работы процедуры последовательного,
побайтного (начиная с младшего байта) вычитания делителя из делимого, а вторые 2
константы нужны для получения истинного остатка от деления.
Наличие “глобальной” (в данном случае) цифры “два” объясняется тем, что делимое
состоит их 2-х байтов.
Естественно, что они обрабатываются последовательно, так как ПИК может
осуществить отдельную операцию только с одним байтом.
Для работы с константами (вызова той из них, которая нужна), организован
вычисляемый табличный переход.
Естественно, что в этом случае, все константы должны располагаться строго “по
адресному ранжиру”, что и имеет место быть.
В начале таблицы располагаются 4 константы, задействованные в процедуре деления
на 1000 и “рихтовки” остатка от этого деления.
dt .24, .252, .232, .3, …
Откуда взялись эти числовые значения?
.1000 = 00000011 11101000 = 03E8h
Младший байт имеет числовое значение .232.
Старший байт имеет числовое значение .3
Их Вы и видите.
Эти 2 числовых значения будут использованы в процедуре получения истинного
остатка от деления (в приложении к 2-байтному числу).
Если числа .232 и .3 проинвертировать, то получатся числа .24 и .252.
Вы также их видите.
Эти 2 числовых значения будут использованы в процедуре последовательного,
побайтного (начиная с младшего байта) вычитания делителя из делимого.

7
Остальные две группы констант (для деления на 100 и на 10) организованы точно по
такому же принципу.
Числа .0 и .255 имеются в них по той простой причине, что для отображения чисел .
100 и .10 нужен только один байт, а для обеспечения нормальной работы
программной процедуры деления, нужно оперировать 2-мя байтами делителя.
По этой причине, делитель и имеет 2 байта.
Просто в случаях деления на 100 и на 10, старший байт делителя всегда равен нулю.
Итак, в таблице “лежат” все необходимые для работы “прибамбасы”.
Можно работать.
Сначала нужно “заложить” в регистры BL и BM двоичное число, форму которого нужно
преобразовать.
Это и имеет место быть.
Непосредственно к ПП преобразования формы числа эта “закладка” отношения не
имеет.
Если данная ПП преобразования формы числа входит в состав какой-то “боевой”
программы, то нужно озаботиться тем, чтобы “на подлете” к ПП преобразования
формы числа, в BL и BM “лежало” что-то полезное.
После этой “закладки”, отрабатываются подготовительные операции.
Об обнулениях распространяться не буду, и так все понятно, а вот о косвенной
адресации пару слов сказать нужно.
В конце подготовительных операций, в регистр FSR записывается адрес регистра LED
самого старшего разряда (LED3), то есть, того регистра, в котором, в конечном итоге,
“осядет” целое число делений на 1000.
Этот адрес только записывается в FSR и не более того.
Обращение к IndF будет не сразу же после этого, а позднее.
Итак, “формальности соблюдены” и можно вычитать из делителя 1000.
На 1-м “витке” полного цикла ПП преобразования формы числа, в регисте Count
“лежит” ноль (см. clrf Count), следовательно, после отработки вычисляемого перехода,
из содержимого регистра BL будет вычтена константа .24.
Еще раз напоминаю, что, хотя и имеет место быть команда суммирования (addwf), но
по факту, происходит операция вычитания, так как байт делителя инвертирован.
Об этом говорилось в предыдущем подразделе.
Так как производятся операции с 2-байтными числами, то соответственно, нужно
обработать и второй байт (BM), но сначала нужно обеспечить возможность переноса
из более младшего разряда.
Значит нужно проверить флаг С, и если он поднялся, то инкрементировать
содержимое регистра BM или не инкрементировать его, что и имеет место быть.
Далее, для того чтобы обработать содержимое регистра более старшего разряда (BM),
нужно сменить константу, то есть, использовать константу старшего разряда делителя.
Значит, для обеспечения выбора этой константы, нужно инкрементировать содержимое
регистра Count (incf Count,W), “уйти” в вычисляемый переход (call CONST), вернуться
из него, а затем исполнить команду addwf BM,F.
Все это и имеет место быть (см. текст программы).
В этом случае, также, по факту, происходит операция вычитания, так как “на свет
Божий извлечена” инвертированная константа делителя старшего разряда (.252).
Более старшего разряда нет. Значит и перенос в него организовывать не нужно (“бабу
с воза, кобыле легче).
Можно “ставить галочку” в текущем LEDе, то есть, инкрементировать его содержимое
(“задокументировать” факт отработки одного вычитания числа 1000 из делимого).
Так как задействуется косвенная адресация, то это “проще пареной репы”: incf IndF,F.
Далее нужно “упасть” на анализ знака остатка, получившегося в результате отработки
текущей (в процессе работы ПП, этих отработок может быть несколько) процедуры
вычитания числа 1000 из делимого, что и имеет место быть: btfsc Status,C.
Примечание: флаг С “срабатывает” по факту исполнения команды addwf BM,F.
Команда incf IndF,F на флаг С не воздействует.
Если в регистре BM будет “лежать” число большее тысячи, то рабочая точка
программы “отфутболивается” на повторное вычитание из делимого тысячи.
Далее снова происходит то, что описано выше, и это “отфутболивание” будет
происходить до тех пор, пока делимое не станет меньше делителя.
8
Обращаю Ваше внимание на то, что в течение всей этой “свистопляски” (в пределах
деления на 1000), содержимое регистра Count равно нулю.
И в самом деле, результат инкремента его содержимого записывается не в регистр
Count, а в регистр W (см. команду incf Count,W).
После того, как будет “засечен” факт отрицательного результата (делимое меньше
делителя), начинается “исправление числового дефекта”, связанного с “лишним”
вычитанием тысячи из делимого (числовое значение остатка не равно требуемому).
Значит нужно перейти на неинвертированную константу сначала младшего разряда
делителя, а затем и старшего.
Для того чтобы обеспечить эту возможность, нужно записать в регистр Count число 2
(“по верху”, “старого” и ставшего не нужным, нуля), что и имеет место быть (bsf
Count,1 - самое оптимальное решение), а затем скопировать его в регистр W (movf
Count,W).
Соответственно, в результате исполнения “вычисляемопереходных дел”, на “свет Божий
извлечется” не инвертированная константа младшего байта делителя (.232).
Далее следует команда addwf BL,F, которую, по факту, уже нельзя назвать командой
операции вычитания.
Почему? А потому, что константа не инвертирована.
В результате ее исполнения, в младшем байте регистра делимого (BL) “осядет”
истинное значение остатка от предшествующего деления на 1000 (в части касающейся
младшего байта этого остатка).
Далее, все по той же причине необходимости обеспечения переноса в более старший
разряд делимого, нужно посмотреть, был перенос (по результату исполнения команды
addwf BL,F) или нет?
Если был, то содержимое регистра BM инкрементируется, а если нет, то не
инкрементируется.
Любой из этих сценариев “упирается” в команду подготовки выбора следующей
константы incf Count,F, которая и исполняется.
После этого делаются “вычисляемопереходные дела”, в результате чего на “свет Божий
извлечется” не инвертированная константа старшего байта делителя (.3).
Далее производится суммирование старшего байта регистра делимого с этой константой,
в результате чего, в старшем байте регистра делимого (BM), “осядет” истинное
значение остатка от предшествующего деления на 1000 (в части касающейся старшего
байта этого остатка).
Теперь можно “ликвидировать перебор” результата деления на 1000, который возник
при последнем вычитании тысячи из делимого (когда делимое стало меньше
делителя).
При наличии процедуры косвенной адресации, это сделать просто: decf IndF,F и “дело
в шляпе”.
После этого, в LED3 будет “лежать” число делений на 1000, соответствующее истине.
Итог: деление на 1000 завершено.
В 2-байтном регистре BM/BL “лежит” двоичное число, десятичный эквивалент которого
равен точному остатку от деления “материнского”, двоичного числа на 1000.
Количество этих делений “ушло” в младший полубайт байта регистра результата
преобразования формы числа самого старшего разряда (LED3).
После этого, можно делить сначала на 100, а затем и на 10.
Для обеспечения такой возможности, нужно
1. сменить текущий LED,
2. сменить текущую группу констант,
после чего повторить все то, о чем шла речь выше.
Первое обеспечивается банальным декрементом содержимого регистра FSR (см.
адресные “прописки” регистров LED0…LED3 в “шапке” программы).
Второе обеспечивается двумя инкрементами содержимого регистра Count (+2).
Объяснение: после выхода рабочей точки программы из процедуры деления на 1000, в
регистре Count “лежит” число 2 (см. bsf Count,1).
Чтобы перейти на первую константу группы констант деления на 100, нужно, чтобы в
регистре Count “лежало” число 4.
Вот Вам и объяснение наличия двух инкрементов.

9
Далее, в целях обеспечения возможности перехода рабочей точки программы в группу
команд работы с остатком от комплексного деления (после окончания деления на 10),
производится анализ содержимого регистра Count на предмет нахождения в нем числа
.11.
Это и есть критерий такого перехода (или не перехода).
В частности, после отработки процедуры деления на 1000 и проверки содержимого
регистра Count на соответствие числу .11, такого соответствия обнаружено не будет, и
рабочая точка программы “улетит” в ПП NEXT, в которой будет отработана процедура
деления на 100.
В регистре BM/BL “осядет” остаток от деления на 100, а в регистре LED2 будет
“лежать” число количества делений на 100.
После выхода из процедуры деления на 100, в регистре Count будет лежать число
4 + 2 = 6.
Затем еще 2 инкремента, и в регистре Count будет “лежать” число 6 + 2 = 8, а это как
раз то, что нужно при делении на 10.
Далее - опять переход в ПП NEXT, в которой будет отработана процедура деления на
10.
В регистре BM/BL “осядет” остаток от деления на 10, а в регистре LED1 будет
“лежать” число количества делений на 10.
После выхода из процедуры деления на 10, в регистре Count будет лежать число
8 + 2 = 10.
Затем еще 2 инкремента, и в регистре Count будет “лежать” число 10 + 2 = 12.
Перебор констант закончен (окончание комплексного деления) и делить больше нечего.
Вот тут-то и срабатывает проверка на число .11.
У Сергея, для этой проверки, задействуется флаг DC (анализ результата исполнения
команды sublw .11 в пределах младшего полубайта), но я заменил его на более
привычный флаг С (то же самое, но в пределах байта).
При вычитании 12-ти из 11-ти, получается отрицательное число, следовательно, вместо
команды goto NEXT исполнится “виртуальный” NOP (команда goto NEXT обходится), и
рабочая точка программы “перескочит” на команду movf BL,W.
Эта и следующая за ней команда (movwf LED0) просто переписывают (через W)
содержимое остатка от комплексного деления в регистр LED0.
Все. Полный цикл программы закончен.
Задача решена.
Далее, в целях обеспечения “сервиса” в ходе отслеживания работы программы, Сергей
“подсуетился” и “поставил программу на счетчик”.
Это означает то, что можно, с комфортом, последовательно (в “полуавтомате”),
отследить все результаты преобразования формы чисел, начиная от двоичного числа,
величину которого можно задать в программе.

Высылаю программу Bin2_4_1.


Я в неё встроил счётчик кол-ва полных циклов программы, который увеличивает свое
значение на единицу с каждым новым циклом.
Соответственно, значение двоичного числа, на входе в ПП преобразования формы числа,
тоже увеличивается.
Таким способом, я прогнал программу по единичным значениям от 0 до 9999.
Программа отработала на все 100%, без ошибок.
На начальном этапе, в счётчик можно записать константу, определяющую, с какого именно
числа нужно начинать преобразование.

;********************************************************************************
; BIN2_4_1.asm Программа, демонстрирующая работу ПП преобразования двоичного
; кода в двоично-десятичный, с перебором всех значений двоичного
; числа, начиная от заданного.
; Используется м/контроллер PIC16F873. Частота кварца 4 Мгц.
; Автор: Рослик Сергей Львович.
;********************************************************************************
; На входе: 2-байтное двоичное число (в 2-байтном регистре BL/BM).
; На выходе: 4-разрядное десятичное число (в младших полубайтах регистров
; LED3...LED0).
10
;********************************************************************************
LIST p=16f873 ; Используется PIC16F873.
__CONFIG 3731H
;================================================================================
; Определение положения регистров специального назначения.
;================================================================================
IndF equ 00h ; Доступ к памяти через FSR.
PC equ 02h ; Счетчик команд.
Status equ 03h ; Регистр Status.
FSR equ 04h ; Регистр косвенной адресации.
;================================================================================
; Присваивание названий биту и месту размещения результатов операций.
;================================================================================
C equ 0 ; Флаг переноса-заема.
F equ 1 ; Результат направить в регистр.
;================================================================================
; "Прописка" регистров общего назначения.
;================================================================================
BL equ 20h ; Младший регистр перекодируемого числа.
BM equ 21h ; Средний регистр перекодируемого числа.
LED0 equ 22h ; Разряд 1.
LED1 equ 23h ; Разряд 10.
LED2 equ 24h ; Разряд 100.
LED3 equ 25h ; Разряд 1000.
Count equ 26h ; Счетчик выбора констант из таблицы.
SecL equ 27h ; Младший регистр счётчика витков.
SecM equ 28h ; Старший регистр счётчика витков.
;================================================================================
org 0 ; Начать выполнение
goto START ; программы с ПП START.
;********************************************************************************

;================================================================================
; Таблица констант делителей (табличный вычисляемый переход).
;============================================================================
CONST addwf PC,F ; Приращение PC на величину содержимого W.
dt .24, .252, .232, .3, .156, .255, .100, .0, .246, .255, .10, .0
;================================================================================

;********************************************************************************
; НАЧАЛО ВЫПОЛНЕНИЯ ПРОГРАММЫ.
;********************************************************************************
; В регистры SecM и SecL записывается двоичное число (“точка отсчета”).
;----------------------------------------------------------------------
START movlw 0 ;
movwf SecM ; Определение начальной
movlw 0 ; “точки отсчета”.
movwf SecL ; Можно определить и иначе.
;================================================================================
; Запись в регистр BM/BL значения текущего двоичного числа.
;================================================================================
COUNTER call INKREM ; Переход в ПП инкремента содержимого
; регистра SecM/SecL (а по факту -> BM/BL).
;----> Возврат по стеку из ПП INKREM.
movf SecL,W ; Загрузка в BM/BL двоичного двухбайтного
movwf BL ; числа, которое будет переведено
movf SecM,W ; в двоично-десятичную форму.
movwf BM ;
;================================================================================
; ПП преобразования двухбайтного двоичного числа в 4-разрядное десятичное число.
;================================================================================
; Подготовительные операции.
;----------------------------------------
BIN2_10 clrf LED1 ; Подготовка к работе
clrf LED2 ; регистров результата
clrf LED3 ; 2/10 преобразования.
11
clrf Count ; Подготовка к работе счётчика выбора
; констант.
movlw LED3 ; Начало процедуры косвенной адресации:
movwf FSR ; запись в FSR адреса регистра LED3.

;================================================================================
; ПП формирования десятичного значения текущего LED с "привязкой" к конкретному
; делителю (константам). Деление происходит путем последовательного вычитания
; делителя из делимого, с подсчетом количества этих вычитаний ("оседает" в
; текущем LED), до момента, когда делитель становится больше делимого.
;================================================================================
NEXT movf Count,W ; Подготовка к выбору константы
; (то есть, к выбору делителя).
call CONST ; Выбор константы для регистра BL.
;----> Возврат по стеку из ПП CONST.
addwf BL,F ; BL-CONST=... (вычитание делителя из
; делимого в приложении к BL).
btfsc Status,C ; Перенос был или нет?
incf BM,F ; Если был, то BM+1=... (перенос в BM)
; Результат - в BM.
incf Count,W ; Если не было (а также после BM+1), то
; подготовка к выбору следующей константы.
call CONST ; Выбор константы для регистра BM.
;----> Возврат по стеку из ПП CONST.
addwf BM,F ; BM-CONST=... (вычитание делителя из
; делимого в приложении к BM).
incf IndF,F ; Подсчёт кол-ва вычитаний
; (текущий LED+1 =... Результат - в LED).
btfsc Status,C ; Перенос был или нет (делимое больше или
; меньше делителя)?
goto NEXT ; Если был (делимое больше делителя), то
; продолжаем вычитать.
;================================================================================
; Работа с остатком от деления.
;================================================================================
bsf Count,1 ; Если не был, то подготовка к выбору
movf Count,W ; константы (с адресом PC+02h) для
; формирования истинного значения остатка.
call CONST ; Выбор константы для регистра BL.
;----> Возврат по стеку из ПП CONST.
;-----------------------------------------
; Формирование истинного значения остатка.
;-----------------------------------------
addwf BL,F ; Операция суммирования содержимого W и BL.
btfsc Status,C ; Перенос был или нет?
incf BM,F ; Если был, то BM+1=... (перенос в BM)
; Результат - в BM.
incf Count,W ; Если не было (а также после BM+1),
; то подготовка к выбору константы.
call CONST ; Выбор константы для регистра BM.
;----> Возврат по стеку из ПП CONST.
addwf BM,F ; Операция суммирования содержимого W и BM.
decf IndF,F ; Устранение "перебора" в текущем LED.
;***********************************************
; Работа с текущей четверкой констант закончена
; (содержимое текущего LED сформировано).
;***********************************************

;================================================================================
; Переход на следующий LED и следующий, "привязанный" к нему, делитель.
;================================================================================
decf FSR,F ; Загрузка в FSR адреса следующего
; регистра LED.
incf Count,F ; Настройка для выбора необходимой константы
incf Count,F ; (для перехода на следующий делитель):
; Count+2=... Результат - в Count.
12
movf Count,W ; Count ---> W.
sublw .11 ; Проверка: все константы (делители)
btfsc Status,C ; перебрали или нет?
goto NEXT ; Если не все, то начинается работа со
; следующим LEDом и с "привязанной" к нему
; группой констант.
; Если все, то работаем с остатком от
; комплексного деления.
;================================================================================
; Работа с остатком от комплексного деления (окончание процедуры).
;================================================================================
movf BL,W ; Загружаем остаток в регистр
movwf LED0 ; десятичного разряда единиц.
goto COUNTER ; Переход на новый виток программы.
;================================================================================

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
; ПП инкремента содержимого регистра SecM/SecL.
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
INKREM incfsz SecL,F ; SecL+1=...
return ; Если результат не=0, то возврат.
incfsz SecM,F ; Если результат =0, то SecM+1=...
return ; Если результат не=0, то возврат.
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

goto START ; "... на колу мочало. Начинаем все


; с начала".
;********************************************************************************
end ; Конец программы.

Работать с этой программой очень просто:


После загрузки ее в проект и ассемблирования, откройте окно RAM.
Сбросьте программу на начало и поставьте точку остановки на команде
goto COUNTER.
Затем щелкаете по кнопке с зеленым светофором или стучите по кнопке клавиатуры
компьютера с названием F9.
В окне RAM, “во всей своей красе”, Вы будете наблюдать результаты преобразований
формы чисел.
Если “стучать” или “щелкать” надоело, то нажмите F9 и держите ее в нажатом
состоянии. Дело пойдет веселее (быстрее).
Обращаю Ваше Внимание на ПП INKREM.
О таком я еще не упоминал (счетчик с использованием условных переходов).
Это ценная “деталька”.
Можете ей смело “укомплектовывать” свой “конструктор”.
Советую обязательно это сделать.
Итак, лично я, убедился, что все это “сооружение” вполне жизнеспособно (и еще как!).
Так как все познается в сравнении, то нужно его произвести.
С этой целью, я “сваял” ПП Sravn.asm:

;********************************************************************************
; Sravn.asm Программа, в которой можно сравнить работу ПП преобразования формы
; числа, предложенной Сергеем Росликом, и стандартной ПП
; преобразования формы числа.
; Используется м/контроллер PIC16F84A. Частота кварца 4 Мгц.
;********************************************************************************
; На входе: 2-байтное двоичное число (в 2-байтном регистре BL/BM).
; На выходе: 4-разрядное десятичное число (в младших полубайтах регистров
; LED3...LED0).
;********************************************************************************
LIST p=16f84a ; Используется PIC16F84A.
__CONFIG 3FF1h
;================================================================================
; Определение положения регистров специального назначения.

13
;================================================================================
IndF equ 00h ; Доступ к памяти через FSR.
PC equ 02h ; Счетчик команд.
Status equ 03h ; Регистр Status.
FSR equ 04h ; Регистр косвенной адресации.
;================================================================================
; Присваивание названий биту и месту размещения результатов операций.
;================================================================================
C equ 0 ; Флаг переноса-заема.
F equ 1 ; Результат направить в регистр.
;================================================================================
; "Прописка" регистров общего назначения.
;================================================================================
BL equ 20h ; Младший регистр перекодируемого числа.
BM equ 21h ; Средний регистр перекодируемого числа.
LED0 equ 22h ; Разряд 1.
LED1 equ 23h ; Разряд 10.
LED2 equ 24h ; Разряд 100.
LED3 equ 25h ; Разряд 1000.
Count equ 26h ; Счетчик выбора констант из таблицы.
Mem equ 1Fh ; Регистр оперативной памяти.
;================================================================================
org 0 ; Начать выполнение
goto START ; программы с ПП START.
;********************************************************************************

;================================================================================
; Таблица констант делителей (табличный вычисляемый переход).
;================================================================================
CONST addwf PC,F ; Приращение PC на величину содержимого W.
dt .24, .252, .232, .3, .156, .255, .100, .0, .246, .255, .10, .0
;================================================================================

;********************************************************************************
; НАЧАЛО ВЫПОЛНЕНИЯ ПРОГРАММЫ.
;********************************************************************************
; По умолчанию, используется число 1D7Eh (.7550), но может быть "заложено" и
; другое число.
;--------------------------------------------------------------------------------
START movlw 1Dh ; Загрузка в BM/BL двоичного 2-байтного
movwf BM ; числа, которое будет переведено
movlw 7Eh ; в двоично-десятичную форму.
movwf BL ;
;####################################################
; ВЫБОР ОДНОЙ ИЗ ДВУХ ПП ПРЕОБРАЗОВАНИЯ ФОРМЫ ЧИСЛА.
;####################################################
; ЕСЛИ ЗАБЛОКИРОВАТЬ ЭТУ КОМАНДУ, ТО
;;; goto Bin2_10 ; ПРОИЗОЙДЕТ ПЕРЕХОД В ПП СЕРГЕЯ РОСЛИКА,
; А ЕСЛИ ЭТУ БЛОКИРОВКУ СНЯТЬ, ТО ПРОИЗОЙДЕТ
; ПЕРЕХОД В СТАНДАРТНУЮ ПП ПРЕОБРАЗОВАНИЯ
; ФОРМЫ ЧИСЛА (Bin2_10).
;==============================================================================
; ПП преобразования 2-байтного двоичного числа в 4-разрядное десятичное число.
;==============================================================================
; Подготовительные операции.
;----------------------------------------
BIN2_10 clrf LED1 ; Подготовка к работе
clrf LED2 ; регистров результата
clrf LED3 ; 2/10 преобразования.
clrf Count ; Подготовка к работе счётчика выбора
; констант.
movlw LED3 ; Начало процедуры косвенной адресации:
movwf FSR ; запись в FSR адреса регистра LED3.
;================================================================================
; ПП формирования десятичного значения текущего LED с "привязкой" к конкретному
; делителю (константам). Деление происходит путем последовательного вычитания
14
; делителя из делимого, с подсчетом количества этих вычитаний ("оседает" в
; текущем LED), до момента, когда делитель становится больше делимого.
;================================================================================
NEXT movf Count,W ; Подготовка к выбору константы
; (то есть, к выбору делителя).
call CONST ; Выбор константы для регистра BL.
;----> Возврат по стеку из ПП CONST.
addwf BL,F ; BL-CONST=... (вычитание делителя из
; делимого в приложении к BL).
btfsc Status,C ; Перенос был или нет?
incf BM,F ; Если был, то BM+1=... (перенос в BM)
; Результат - в BM.
incf Count,W ; Если не было (а также после BM+1), то
; подготовка к выбору следующей константы.
call CONST ; Выбор константы для регистра BM.
;----> Возврат по стеку из ПП CONST.
addwf BM,F ; BM-CONST=... (вычитание делителя из
; делимого в приложении к BM).
incf IndF,F ; Подсчёт кол-ва вычитаний
; (текущий LED+1 =... Результат - в LED).
btfsc Status,C ; Перенос был или нет (делимое больше или
; меньше делителя)?
goto NEXT ; Если был (делимое больше делителя), то
; продолжаем вычитать.
;================================================================================
; Работа с остатком от деления.
;================================================================================
bsf Count,1 ; Если не был, то подготовка к выбору
; константы (с адресом PC+02h)
movf Count,W ; для формирования истинного значения
; остатка.
call CONST ; Выбор константы для регистра BL.
;----> Возврат по стеку из ПП CONST.
;-----------------------------------------
; Формирование истинного значения остатка.
;-----------------------------------------
addwf BL,F ; Операция суммирования содержимого W и BL.
btfsc Status,C ; Перенос был или нет?
incf BM,F ; Если был, то BM+1=... (перенос в BM)
; Результат - в BM.
incf Count,W ; Если не было (а также после BM+1),
; то подготовка к выбору константы.
call CONST ; Выбор константы для регистра BM.
;----> Возврат по стеку из ПП CONST.
addwf BM,F ; Операция суммирования содержимого W и BM.
decf IndF,F ; Устранение "перебора" в текущем LED.
;********************************************************************************
; Работа с текущей четверкой констант закончена
; (содержимое текущего LED сформировано).
;********************************************************************************
;================================================================================
; Переход на следующий LED и следующий, "привязанный" к нему, делитель.
;================================================================================
decf FSR,F ; Загрузка в FSR адреса следующего
; регистра LED.
incf Count,F ; Настройка для выбора необходимой константы
incf Count,F ; (для перехода на следующий делитель):
; Count+2=... Результат - в Count.
movf Count,W ; Count ---> W.
sublw .11 ; Проверка: все константы (делители)
btfsc Status,C ; перебрали или нет?
goto NEXT ; Если не все, то начинается работа со
; следующим LEDом и с "привязанной" к нему
; группой констант.
; Если все, то работаем с остатком от
; комплексного деления.
15
;================================================================================
; Работа с остатком от комплексного деления (окончание процедуры).
;================================================================================
movf BL,W ; Загружаем остаток в регистр
movwf LED0 ; десятичного разряда единиц.

goto $ ; СТОП-МАШИНА!
;********************************************************************************

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; СТАНДАРТНАЯ ПП ПРЕОБРАЗОВАНИЯ 2-БАЙТНЫХ ДВОИЧНЫХ ЧИСЕЛ В 4-РАЗРЯДНЫЕ
; ДЕСЯТИЧНЫЕ ЧИСЛА.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Подготовка к преобразованию.
;================================================================================
Bin2_10 bcf Status,C ; Сброс флага переноса-заема.
movlw .16 ; Зпись в регистр Count числа проходов
movwf Count ; преобразования, равного суммарному
; количеству битов 2-разрядного регистра BM/BL
; (8*2=16).
clrf LED0 ; Сброс в 0 содержимого регистра LED0.
clrf LED1 ; -------"------ LED1.
clrf LED2 ; -------"------ LED2.
clrf LED3 ; -------"------ LED3.
;-------------------------------------------------------------------------------
; Примечание: процесс преобразования заканчивается при уменьшении числа проходов
; преобразования, которые заложены в регистр Count (.16), до нуля.
;================================================================================
; Циклический сдвиг влево.
;================================================================================
Loop16 rlf BL,F ; Циклический сдвиг влево 2-байтного двоичного
rlf BM,F ; числа, записанного в 2-байтном регистре
; BM/BL, на одну позицию, через бит С регистра
; STATUS.
rlf LED0,F ; Циклический сдвиг влево 2-байтного двоичного
rlf LED1,F ; числа, записанного в группе регистров
; LED0/LED1, на одну позицию, через бит С
; регистра STATUS.
decfsz Count,F ; Декремент (-1) содержимого регистра Count с
; сохранением результата в нем же.
goto adjDEC ; Если результат не=0, то переход в ПП adjDEC
; Если результат =0, то программа
; исполняется далее.
;================================================================================
; Поразрядное распределение содержимого регистров LED0 и LED1
; (их полубайтов) по младшим полубайтам регистров LED0...3.
;================================================================================
swapf LED1,W ; Запись старшего полубайта LED1
andlw 0Fh ; в младший полубайт LED3.
movwf LED3 ; --------------------------------

movfw LED1 ; Запись младшего полубайта LED1


andlw 0Fh ; в младший полубайт LED2.
movwf LED2 ; --------------------------------

swapf LED0,W ; Запись старшего полубайта LED0


andlw 0Fh ; в младший полубайт LED1.
movwf LED1 ; --------------------------------

movfw LED0 ; Запись младшего полубайта LED0


andlw 0Fh ; в младший полубайт LED0.
movwf LED0 ; --------------------------------
;--------------------------------------------------------------------------------
; Конец распределения. В младших полубайтах регистров LED0...3 записаны
; двоично-десятичные числа в порядке возрастания разрядности.
16
; Старшие полубайты = 0.
;--------------------------------------------------------------------------------
goto $ ; СТОП-МАШИНА!

;================================================================================
; Запись в регистр FSR адресов регистров LED0, LED1 для дальнейшей косвенной
; адресации к ним в ПП adjBCD.
; Переход к обработке следующего LEDа - после возврата по стеку.
;================================================================================
adjDEC movlw LED0 ; Запись в регистр FSR, через регистр W,
movwf FSR ; адреса регистра LED0 с дальнейшим переходом
call adjBCD ; в ПП adjBCD (адрес следующей команды
; закладывается в стек).
;---> Возврат по стеку из ПП adjBCD.
movlw LED1 ; -----------------------------
movwf FSR ; То же самое для регистра LED1.
call adjBCD ; -----------------------------
;---> Возврат по стеку из ПП adjBCD.
goto Loop16 ; Проход всех LED (с LED0 по LED1). Переход в
; ПП Loop16, то есть на следующее кольцо
; числовых преобразований.
;================================================================================
; Основные операции преобразования двоичных чисел в двоично-десятичные:
; операции сложения LED0...3 и констант 03h,30h с условиями по 3-му и 7-му битам.
;================================================================================
adjBCD movlw 3 ; Сложить содержимое текущего LED с числом
addwf 0,W ; 03h, c записью результата операции, через
movwf Mem ; регистр W, в регистр Mem.
btfsc Mem,3 ; Анализ состояния 3-го бита регистра Mem.
movwf 0 ; Если бит № 3 =1, то содержимое регистра Mem
; копируется в текущий LED.
movlw 30 ; Если бит №3 =0, то содержимое текущего LED
addwf 0,W ; складывается с константой 30h, с последующей
movwf Mem ; записью результата операции, через регистр
; W, в регистр Mem.
btfsc Mem,7 ; Анализ состояния 7-го бита регистра Mem.
movwf 0 ; Если бит №7 =1, то содержимое регистра Mem
; копируется в текущий LED.
retlw 0 ; Если бит №7 =0, то регистр W очищается и
; происходит возврат по стеку в ПП adjDEC.
;================================================================================
end ; Конец программы.

ПП Sravn.asm представляет собой “набор” из 2-х подпрограмм преобразования формы


числа.
Переход в ту или иную из них зависит от того, заблокирована или нет команда
goto Bin2_10 (выделено красным цветом).
По умолчанию, эта команда заблокирована (работает ПП Сергея), но ее можно
разблокировать (работает стандартная ПП).
Соответствующие пояснения даны в тексте программы.
Точки остановки нужно назначать на командах goto $ (тоже выделены красным
цветом).
Программа составлена под PIC16F84A.
Считаю, замеряю и сравниваю:

Сравниваются: Количество команд Время преобразования числа .7550 (в м.ц.)


ПП Сергея Рослика 37 + 13 = 50 528
Стандартная ПП 44 640

Проигрыш ПП Сергея, относительно стандартной ПП, составляет 6 команд, но зато


выигрыш по скорости составляет 112 машинных циклов.
В большинстве случаев, второе важнее первого, да и 6 команд, по меркам объема
PC, это мизер.
17
Вывод: по своим качественным показателям, ПП преобразования 2-байтного двоичного
числа в 4-разрядное десятичное число, по сравнению с аналогичной, стандартной ПП
преобразования формы числа, более выигрышна.
Вопрос: “Будет ли иметь место такой выигрыш в случае работы с 3(и более)-байтным
двоичным числом”?
Ответ: такого выигрыша не будет, так как “масса” ПП Сергея значительно возрастет.
Значит, еще один вывод: ПП Сергея нужно применять при байтности (имеется ввиду
“входное”, двоичное число) не более двух (включительно).
При байтности от трех и выше, нужно применять стандартную ПП.
Но и “потолок” в 4 десятичных разряда это совсем не мало.
Имеется множество устройств, в которых большей разрядности и не требуется.
В этих случаях, ПП Сергея более предпочтительна и выгоднее применять именно ее.

Почему я так скурпулезно “просканировал” ПП Сергея?


А потому, что это не “моргалка” или “пищалка”, а “глобальная” процедура,
применяемая сплошь и рядом (“важняк”).
“Статус” этой ПП настолько высок, что переоценить его сложно (“в этой игре ставки
крупные”).
Чтобы быть до конца объективным, нужно сказать, что я не исключаю “наличие в
природе” ПП, аналогичной ПП Сергея, но я могу сказать совершенно точно (“нюх”
имеется), что Сергей “родил” ее своими усилиями и своей головой, а это, вне
зависимости от чего-либо, дорогого стоит.
К тому же, один и тот же принцип можно реализовать различными способами, в том
числе и не самыми оптимальными (например, при использовании языков
программирования высокого уровня).
Здесь же, все просчитано “от и до”, так как в наличии имеется совсем не глупый
человек, да еще и не плохо работающий в “чистом” ассемблере.
Не знаю как Вы, а я получил от работы Сергея очередное удовольствие.
Сергей, снимаю шляпу. “Безумству храбрых поем мы песню”. Отличная работа.
“Хулиганьте” в таком же духе и далеко пойдете.
Если Вам нужны мои “виртуальные, игрушечные погоны офицера программных войск”,
то считайте, что я Вам их вручил (в каждой шутке есть доля истины).
А если серьезно, то поздравляю Сергея с победой.
Да не с той победой, коих будет множество (я уверен в этом), а с самой главной -
победой над самим собой, ведь что греха таить, далеко не всем дано победить
неуверенность в своих силах, в комплексе с реальным подтверждением сего отрадного
факта на практике.
Я совершенно точно знаю, что среди Вас имеется не мало “зубастых” людей (хватка
как у буль-терьера), которые, по “зубастости”, как минимум, ни в чем не уступают
Сергею, и о которых можно сказать то же самое.
А раз это так, то творческие перспективы будущей работы радуют и внушают
оптимизм.
Значит будет интересно и не “академично” (то есть, жизненно).
Интересно (по крайней мере, лично мне) хотя бы потому, что совершенно нельзя
предсказать, “в какую степь улетит Ваша буйная фантазия” и в чем это выразится.
Надеюсь, что Сергей окончательно “загрызет” эту тему, и мы узнаем от него что-то
новенькое.
Советую всем Вам (и себе в том числе), с утречка, периодически, потихоньку
“подтачивать надфилем свои клыки”.
Проблем еще море, и всем им нужно “перегрызть глотки”.
Острые “клыки” нынче в большой цене.
Работаем дальше…

18
"Практикум по конструированию устройств на PIC контроллерах"      http://ikarab.narod.ru       E-mail: karabea@lipetsk.ru

19