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

2-2/12.

Упреждающая подготовка к "глубочайшему осознанию сермяжной сути"


тех блочно-страничных дел, которые будут делаться в следующем подразделе
(работа с PCLATH в случаях расположения текста программы на нескольких
страницах памяти программ и наличия большого количества подпрограмм
вычисляемых переходов).

Теперь нужно кое-что объяснить (хотя, по большому счету, это относится вообще ко
всей моей информации).
Если я сейчас начну объяснять работу "новой" программы (BP_9.asm), то вполне
вероятен "геморройнопонятийный конфуз", связанный с "блочно-страничными делами".
Мой "внутренний цензор" настоятельно советует сделать это только после целевого
растолковывания "сермяжной сути всего этого безобразия/мозгозаворота".
И игнорировать совет этой таинственной и могущественной субстанции я не буду, так
как, во-первых, дураком себя не считаю, а во-вторых, не желаю ставить Вас в
дурацкое положение.
К тому же, речь идет не только о конкретной программе, а вообще о всех
программах, в которых имеются ПП вычисляемых переходов, а тем паче, о тех
программах, объемы текстов которых "зашкаливают" за одну страницу памяти программ
(без соответствующих знаний/навыков, вообще "Караул!!!").
Коррекция положения нижней части челюсти. Боевая настройка биофункций. Старт.

Итак, с учетом того, что сделано на данный момент, объем текста текущей программы
"зашкалил" за первую страницу памяти программ.
Пояснение: 1-й страницей памяти программ я называю ту страницу, которая в
даташитах называется нулевой страницей памяти программ.
Соответственно, далее (и "до того" тоже), вся нумерация страниц памяти программ, в
моем толковании, будет иметь вид 1, 2, 3, … страница, а не 0, 1, 2, … страница.
Причина: не нравится мне нулевая страница. Образ (аналогию с книгой) сильно
портит. Где это видано, чтобы книга начиналась с нулевой страницы?
Если какой угодно стандарт вступает в противоречие с удобным образом (жизненной
аналогией), то лично я, выбираю образ (однозначно) и создаю свой личный стандарт.
То же самое можно было бы "провернуть" и по отношению к нумерации банков, но я
не стал ее менять, так как образ банка мне абсолютно "по барабану" (в душе ничего
не "шевелится". "Бревно").
Не был я в этом образе. И не буду, так как не хочу.
Еще раз обращаю Ваше внимание на то, что образы это не блажь воспаленного
воображения и не признак ненормальности, а подчинение подсознания
(мощнейший "инструмент"!!!) сознанию.
Тем, кто это игнорирует, я совсем не завидую, так как такого рода упорство (а может
быть и лень) резко снижает вероятность особо эффективных "падений на голову
разнообразнейших яблок", что эквивалентно потере чего-то важного.
Так что не обессудьте.
Ранее, в подразделе 1/3 второй части "Практикума…", была затронута тема
числовой коррекции содержимого регистра PCLATH, как в общем виде, так и
применительно к тем конкретным "железякам", которые "подвергалась пыткам".
При этом, основное внимание было уделено числовой коррекции содержимого регистра
PCLATH с помощью операторов high и low, обеспечивающих универсальность такой
коррекции (комфорт).
Начну с оператора low.
Если речь идет о какой-то рациональности, то оператор low целесообразно применять
не во всех случаях (но можно и во всех. Не возбраняется), а только в тех, когда есть
"реальная угроза прохождения границ", между блоками памяти программ, через
таблицы вычисляемых переходов.
Намек: если "раскидывать" ПП вычисляемых переходов абы как (системность
отсутствует), то эта "реальная угроза" будет присутствовать всегда и о рациональности
можно не мечтать.

1
В операторе low, больше всего привлекает то, что применив его, можно не "забивать
себе голову" указанной выше проблемой.
То есть, речь идет о своего рода комфорте: в случае задействования оператора low,
при условии организации соответствующей, программной коррекции содержимого
регистра PCLATH, ПП вычисляемых переходов можно "раскидать" (в PC) как угодно.
Не обращая внимания на "границы" между блоками.
Лично я, совсем не против комфорта, но в пределах выгодного/разумного, ведь
общеизвестно, что за комфорт нужно чем-то расплачиваться.
А именно, "расплата" заключается в увеличении количества команд и соответственно, в
"затяжке" времени отработки того, что связано с ПП вычисляемого перехода.
При таком "раскладе", если в цикле программы отрабатывается много таких
подпрограмм, то и "затяжка" увеличивается кратно.
Если это время не лимитировано или устраивает, и в памяти программ "полно
свободного места", то и ограничений по "массовому применению" оператора low, нет.
Применяйте на здоровье. Это очень удобно.
В тех же случаях, когда количество команд и скорость важны, а также если речь идет
о принципиальной (эстетическо-идейной) минимизации объема программы (не ее текста,
а того, что "лежит" в PC), лучше обойтись без оператора low.
Для этого, всего-то и нужно, по-умному "раскидать" ПП вычисляемых переходов в
памяти программ.
Начиная с сАмого ее "верха", а не с "геморройных середины и низа" (условно).
Обращаю Ваше внимание на слово "сАмого".
Если в программе нет ПП прерывания, то в идеале, речь идет о нулевом адресе PC.
В этом случае, "блочная фора" - 255 команд (ячеек PC).
Если Вы "свАлите", в эту "зону", все или часть подпрограмм вычисляемых переходов
(с учетом того, что блок не "резиновый"), то Вы совсем не ошибетесь, так как, в ходе
дальнейшей работы над текстом программы (изменения ее "массы"), все эти ПП
вычисляемых переходов (группа) либо вообще не будут смещаться вниз, либо
будут, но в пределах дозволенного ("расшифровка" - см. ниже).
Соответственно, речь идет о двух вариантах:

1. По ходу дальнейшей работы над текстом программы, в группу ПП вычисляемых


переходов (она не должна выходить за "границы" блока!), не вносится никаких
корректив ("Масса" неизменна. Самый удобный вариант. Проблем нет).

2. По ходу дальнейшей работы над текстом программы, в группу ПП вычисляемых


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

Если "все формальности соблюдены", то в любом из этих случаев, все изменения,


происходящие в "основном теле" программы - "по барабану", так как они не приведут
к смещению (в PC) группы (групп) подпрограмм вычисляемых переходов.
Почему? Потому, что эта группа "лежит" выше "основного тела" программы.
И это "дельце можно провернуть" не только с целью "избавления" от
оператора low, но и вообще во всех случаях наличия, в программах,
подпрограмм вычисляемых переходов.
Конкретнее.
Если произведена корректировка "массы" группы ПП вычисляемых переходов, в сторону
увеличения "массы" (в группу добавлена "новая" ПП или в "старые" ПП добавлены
дополнительные команды), то после этого, обязательно нужно убедиться в том, что
"перехода нижней границы" блока нет (контроль - в окне ROM).
Примечание: на мой взгляд, дополнительную ПП удобнее всего "врезАть в самый низ"
группы. Но можно и выше (те ПП, которые будут расположены ниже этой "врезки",
сместятся вниз).
В том случае, если, в результате такого "катаклизма", "граница будет нарушена"
("Застава! В ружьё!"), нужно исключить, из этой группы, одну (или несколько. Зависит
2
от "объема корректив") подпрограмму вычисляемого перехода и переместить ее в
"нижележащий" (следующий/соседний снизу) блок памяти программ.
Вплоть до организации "новой" группы, если в "нижележащем" блоке памяти программ,
вообще никакой "вычислительнопереходной" группы не имеется.
При этом, опять же, нужно убедиться в том, что и в этом, "нижележащем" блоке,
"граница может спать спокойно".
Ну и так далее, по "цепочке" (если групп несколько). По направлению типа "вниз".
Если произведена корректировка "массы" группы, в сторону уменьшения "массы", то
нужно проконтролировать то же самое, но только с учетом того, что произойдет
смещение "нижележащего" вверх.
Если "нижележащее" есть еще одна группа ПП вычисляемых переходов, то вполне
возможны проблемы с "нарушением верхней границы" блока.
В этом случае, ее (группу) нужно "загнать в свой загон" путем смещения вниз
(об этом - ниже).
Примечание: в каждом блоке памяти программ, своя, отдельная "застава", которая
охраняет "свой кусок границы".
Эти ребятишки и засекут нарушителя, и доложат начальнику заставы (программисту), а
уж начальник заставы сам решает, командовать "Застава! В ружьё!" (хороший
начальник) или не командовать (плохой начальник).

Могут быть различные варианты такого рода "наведения верхнего порядка", но смысл
один и тот же - приведение всех групп ПП вычисляемых переходов к такому
состоянию, при котором "переходы границ" отсутствуют.
Если выражаться по-русски, то эту "процедуру" можно назвать "устаканиванием".
Во многих случаях, "устаканиваться" даже и не нужно, так как все изначально
"устаканено" ("формальности соблюдены" и изменений "массы" нет), но случаи всякие
бывают. На то они и случаи.
Предположим, что все окончательно "устаканилось".
В том смысле, что до окончания работы с программой (и на дальнейшие "веки
вечные"), "масса" всех групп ПП вычисляемых переходов неизменна.
Получается очень даже симпатично: вне зависимости от того, что будет
"твориться в основном теле" программы, "угроза прохождения границы",
между блоками памяти программ, через таблицу вычисляемого перехода, будет
напрочь отсутствовать.
Вывод: с учетом сказанного, все ПП вычисляемых переходов нужно "валить"
(по-умному) в "верхушку" памяти программ (если говорить о тексте программы, то
в "верхушку" верхней "обслуги").
Если в программе есть ПП прерывания, то смысл тот же самый, только с учетом того,
что первую группу ПП вычисляемых переходов нужно разместить сразу же после ПП
прерывания (именно так и сделано в программах BP_ …).
В этом случае, задача несколько усложняется, так как по ходу работы, в ПП
прерывания могут быть внесены изменения, но все-равно это лучше, чем "засовывать"
ПП вычисляемых переходов в "середину"/"конец" (условно) "основного тела" программы.
В последнем случае, вероятность смещения, при корректировке текста программы,
высока.
И она тем выше, чем ближе, к "концу основного тела" программы, расположена группа
ПП вычисляемых переходов (или отдельная ПП вычисляемого перехода).
Например, если группа ПП вычисляемых переходов (или несколько таких групп) будет
"дислоцироваться" в "районе конца" текста программы (в нижней "обслуге"), то
результатом большинства корректировок "вышележащего" текста программы, будет
смещение этой группы в PC (вверх или вниз).
Естественно, что не все эти смещения приведут к "вычисляемо-переходным бякам", но
некоторые приведут.
Короче, вопрос везения. Может повезти, а может и нет.
На мой взгляд, такой подход к делу совершенно не серьезен ("детский сад").
Если не повезет, то неизбежно придется вплотную познакомиться с "Гитлер капутом".
Радости от него вообще никакой. Одна подлость, ехидство и изнасилование мозгов.
Причем, в особо извращенной форме (бывает такое, что "мозги завязываются на
N-узлов").
3
Думаю, что многие из Вас совсем не по наслышке знакомы с этим "капутом".
Примечание: а уж как я с ним знаком … Ближе некуда. Если бы не его подлость, то
был бы другом.
Вывод: "Учиться, учиться и еще раз учиться!" (… сами знаете кто. Присоединяюсь).
В случае же того, на что я Вам намекаю (с учетом "соблюдения формальностей и
устаканивания"), смещаться будет то, что расположено ниже групп ПП вычисляемых
переходов, и эти группы, при любом "объеме" корректировки всего того, что "лежит"
ниже, будут "стоять как вкопанные".
А раз это так, то от применения оператора low можно просто-напросто отказаться.
Следствием этого будет уменьшение объема текста программы и увеличение скорости
отработки ее полного цикла (по сравнению со случаем применения оператора low).
Теперь вдумайтесь в сказанное.
Это есть не что иное, как "элементарное наведение порядка", результатом которого
является некий "выигрыш".
Просто нужно знать, зачем и как именно его "наводить".
"Ковыляю" дальше.
Вопрос: "А что делать с промежутками между группами? Ведь вероятность
идеального "вписывания" в блок, группы ПП вычисляемых переходов, хотя и есть, но
мала".
Ответ: все правильно. Значит нужно озаботиться тем, как именно организовать эти
промежутки. Для случаев "неидеального вписывания" (их - подавляющее большинство).
Такая постановка вопроса неумолимо наталкивает на мысль о том, что соседние
группы подпрограмм вычисляемых переходов нужно как-то "разнести" в памяти
программ (не абы как, а по-умному, отделить друг от друга), а иначе, все
"вышележащее предтарахтенье и гроша ломаного не стОит".
Пояснение: промежутком я называю количество ячеек памяти программ между
последней командой предыдущей (верхней) группы подпрограмм вычисляемых
переходов (последней, по тексту, команды retlw xxx) и 1-й командой последующей
(нижней) группы подпрограмм вычисляемых переходов (addwf PC,F), которая
(команда) расположена в сАмой "верхушке" блока.
Каковы "механизмы разнесения"?

1. В простейшем случае, смещение части текста программы осуществляется при


помощи N-количества NOPов.
Сколько NOPов будет "настукано" (в "нужном месте"), таковым и будет смещение
"нижележащей" части программы вниз.
По-моему, тут и комментировать-то нечего.
При помощи N-количества NOPов, можно сместить часть текста программы на любое
количество позиций (ячеек PC), но в данном случае, смещение нужно произвести так,
чтобы 1-я команда addwf PC,F последующей (по отношению к предыдущей) группы
подпрограмм вычисляемых переходов, "дислоцировалась" либо в самом начале
последующего блока PC (смещение равно промежутку), либо ниже, но желательно, в
непосредственной близости от начала последующего блока PC (смещение с тем или
иным превышением промежутка).
В части касающейся такого смещения, "компромиссную конкретику" определяет
программист (с учетом личностного фактора и существующих, программных реалий).

2. В тексте программы, после окончания текста предыдущей группы подпрограмм


вычисляемых переходов, "настукивается" директива ORG, с указанием адреса (в PC),
на который нужно сместить (вниз) всю ту часть программы, которая расположена ниже
этой директивы.
В том случае, если за последней командой предыдущей группы подпрограмм
вычисляемых переходов, следует 1-я команда последующей группы подпрограмм
вычисляемых переходов (никакой "врезки, в стык" между ними, нет), 1-я команда
последующей группы подпрограмм вычисляемых переходов (addwf PC,F) будет
"дислоцироваться" по адресу, указанному в "рабочей" части директивы ORG.
Соответственно, вниз сместится и вся та часть программы, которая расположена ниже
этой команды.

4
При помощи директивы ORG, можно задать любой адрес (произвести любое
смещение), но в данном случае, нужно задать адрес той ячейки последующего (по
отношению к предыдущему) блока памяти программ, которая "дислоцируется" либо в
самом начале последующего блока PC (смещение равно промежутку), либо ниже, но
желательно, в непосредственной близости от начала последующего блока PC
(смещение с тем или иным превышением промежутка).
И эту "компромиссную конкретику" также определяет программист.

3. В любой более-менее сложной программе, имеется какое-то количество


подпрограмм, вызываемых командой call.
Вот их-то и можно "врезать в стыки" между соседними группами подпрограмм
вычисляемых переходов.
При этом желательно выбрать ту ПП, вызываемую командой call, объем которой не
приводит к слишком сильному смещению вниз (относительно начала/"верхушки" блока)
1-й команды группы подпрограмм вычисляемых переходов (что-то типа
"перебора/перелета". "Недобор/недолет" не допустим).
В идеале, количество команд "врезаемой" подпрограммы, должно быть равно
промежутку, но такое редко когда бывает.
Практически всегда, речь идет о "врезках", количество команд которых, в той или иной
мере, превышает промежуток.
Каковы конкретные превышения?
А это зависит от "объема" тех врезок, которые имеются в наличии.
Тут особо-то и не развыбираешься. Что есть, из того и нужно выбирать.

Первые 2 способа смещения просты, и если в PC "полно свободного места", их


вполне можно применить (на мой взгляд, второй способ более симпатичен), но их
реализация связана с тем или иным снижением эффективности использования
возможностей памяти программ.
И в самом деле, NOPы 1-го пункта никогда исполнены не будут, так как перед ними
происходят возвраты по стеку (то есть, речь идет не о задержке, а о смещении), и
директива ORG, в этом отношении, à "хрен редьки не слаще".
В любом из этих двух случаев, некоторая часть ячеек PC "приобретает статус" некоего
"балласта" (хотя и не лишенного смысла).
Если групп ПП вычисляемых переходов много, то в сумме, "масса балласта" может
оказаться вполне приличной ("моторесурс PC разбазаривается").
При всем моем величайшем уважении к первым двум пунктам, глядучи на них, "мое
сердце рыдает, стонет и обливается кровью".
Поэтому, во всех программах, которые я "терзал" в этой теме, использовался 3-й
вариант (сугубо личностный выбор).
К примеру, последняя программа (BP_8.asm).
В соответствии с "вышележащей концепцией", все подпрограммы вычисляемых
переходов 1-й страницы памяти программ (про 2-ю страницу à отдельный разговор)
"кнутами согнаны в 3 стада", каждое из которых имеет свой, вполне осмысленный
"загон" (намек на блоки памяти программ).
Все эти "загоны" располагаются исключительно в пределах верхней "обслуги".
В условиях наличия относительного "устаканивания массы" ПП прерывания (ранее, она
была более-менее капитально проработана), эти "загоны" организуются достаточно
просто.
В нижней "обслуге" 1-й страницы памяти программ, ни одной подпрограммы
вычисляемого перехода нет.
Откройте окно ROM и поинтересуйтесь началами/концами этих "загонов".
После этого, Вы убедитесь в том, что все 3 группы подпрограмм вычисляемых
переходов, которые имеются в наличии, "дислоцируются" строго в "границах" первых
трех блоков 1-й страницы памяти программ.
На "стыках" между этими блоками, Вы увидите то ("врезки", в виде ПП, вызываемых
командой call), что совсем не является подпрограммами вычисляемых переходов
(им PCLATH абсолютно "по барабану").
Также обращаю Ваше внимание на то, что наряду с группами подпрограмм
вычисляемых переходов, в верхнюю "обслугу" вынесены такие "устаканенные" (ранее
5
отработанные/неизменяющиеся/внушающие доверие) подпрограммы, "массу" которых
изменять не требуется.
Исключением является только ПП ENTER_BF, в которой я "слегка подрихтовал"
концовку, но это не привело к "вычисляемопереходной бяке", по причине наличия
заранее организованного, "ефрейторскоблочного зазора".
При таком "раскладе", необходимость в использовании оператора low отпадает.
Соответственно, можно применить классические ПП вычисляемых переходов (без
"врезок"), что и есть суть "командноскоростного" выигрыша (по сравнению со случаями
использования "врезок").
Единственное неудобство - "устаканивание".
В случае отсутствия ПП прерывания, можно сказать, что это неудобство минимально.
В случае наличия ПП прерывания - похуже.
В этом случае, степень неудобства зависит от степени "устаканивания" ПП прерывания.
Но в любом случае, неудобство это не тупик.
И тем более для человека, который свободно ориентируется в "блочно-страничных
делах".
Именно для того, чтобы у Вас, в будущем, не было никаких неразрешимых проблем с
подобного рода ориентацией, в контекст текущей темы и "врезан" этот важный (с моей
точки зрения) разговор.
И именно в данный момент он наиболее предпочтителен, так как, в дальнейшем,
можно свериться с "живой" программой, которая обслуживает вполне конкретную
"железяку" ("привязка к жизни").

Перехожу к оператору high.


А вот его, полностью не проигнорируешь.
Вернее, полностью проигнорировать можно, но только через усложнение работы.
Это с одной стороны.
С другой стороны, коррекция содержимого регистра PCLATH, с помощью оператора
high, это 2 команды.
А если нужно перейти, например, в 1-й блок 1-й страницы?
Проще написать clrf PCLATH (одна команда).
А если нужно перейти, например, с 1-го блока 1-й страницы во 2-й блок 1-й
страницы?
Проще написать bsf PCLATH,0.
И так далее. Имеются другие, "однокомандные" варианты.
С учетом сказанного, оператор high есть смысл применять, например, в случае
перехода из 2-го в 3-й блок 1-й страницы (0000 0001 à 0000 0010), так как в этом
случае (а также и в других, подобных случаях), при любом "раскладе", как минимум,
нужны 2 команды.
Если такое имеет место быть, то вне всяческих сомнений, комфортнее/удобнее
применить две команды, связанные с оператором high, чем две команды побитной
(bcf/bsf) или побайтной (movlw/movwf) коррекции содержимого регистра PCLATH.
В последнем случае, "степень напряжения мозгов" выше, чем в первом случае, хотя,
можно выбрать или "то", или "сё" (личное дело).
Еще одна особенность.
Если применяется оператор high, то нужно "держать в поле зрения" аккумулятор (W).
Вопрос: "Почему/зачем"?
Ответ: потому/затем, что в случае использования оператора high (и low тоже),
задействуется регистр W.
Это неумолимо означает то, что если переход (с использованием high), между
блоками/страницами памяти программ, осуществляется сразу же после сохранения, в
регистре W, какого-то "важного" числа, то это число, после исполнения команды
movlw high ABC (ABC - условное название метки/ПП), будет "моментально уничтожено"
записью "по верху" (типа "то, что нажито непосильным трудом, превратилось в прах").
Эта "бяка" вынуждает, перед применением оператора high, сохранять содержимое W в
каком-нибудь регистре общего назначения, а после применения оператора high,
копировать содержимое этого регистра в W.
И в данном случае, никуда от этого не денешься.
Таким образом, получается уже не 2, а 4 команды.
6
А если, при таком "раскладе", нужно перейти, например, в 1-й блок 1-й страницы
(clrf PCLATH и все дела)?
Что выгоднее, 1 команда или 4 (результат один и тот же) ?
Эти примеры я привожу вовсе не для того, чтобы "охаять" оператор high.
Во многих случаях, по совокупности причин, его применение оказывается наиболее
предпочтительным, но "молиться" на него не стОит.
У него есть свои "слабости".
Значит, если речь идет о хозяйском подходе к делу (а проще говоря, о
профессионализме), нужен разумный компромисс, то есть, нечто, "стремящееся к
максимальной грамотности" технического решения.
Именно это я и хочу подчеркнуть.
И еще я хочу сказать то, что блочно-страничные переходы это такой "суперважняк"
(особенно при "ваянии" объемистых программ), который абсолютно не выгодно "пинать
ногами" (это все-равно, что "пинать" самого себя).
В них лучше "въехать" как следует.
В идеале, все блочно-страничные переходы должны быть под "жесточайшим,
въедливым и неусыпным" контролем.
Естественно, для того чтобы это имело место быть, нужно "повариться в этом соку" и
"заложить в свою черепную коробку" определенное количество нужной информации.
Проще и эффективнее всего, достигнуть этой "нирваны" в ходе "разборов конкретных
полетов".
В контексте текущей темы, такая возможность и предоставляется.
Советую Вам ее не упустить.
Речь пойдет о "вырезках" из программы BP_9.asm, которая будет предоставлена в
следующем подразделе.
В ней более двух тысяч команд (работа на двух страницах памяти программ) и около
трех десятков ПП вычисляемых переходов, так что "тренировочка/драчка" будет
славной.
Обращаю Ваше внимание на то, что результатом одной-разьединственной, "блочно-
страничной" ошибки (любой) будет "глюк той или иной степени тяжести" (такова
суровая правда жизни).
Этого допустить нельзя. Дело чести. И не только офицера, но и всех остальных.

Напоминаю основные положения, сформулированные ранее (подраздел 1/3 второй


части "Практикума…"), и кратко, но ёмко, формулирую "правила PCLATH-игры":

1. Память программ разделена на страницы программ.


В памяти программ PIC16F873A, таких страниц две:
страница 1 и страница 2.
Каждая страница памяти программ состоит из 8-ми блоков памяти
программ.
Если в наличии имеются 2 страницы памяти программ (как в PIC16F873A),
то состояния битов регистра PCLATH с №№ 7,6,5,4 не важны.
2. Выбор блока памяти программ определяется числом (00h … 07h. Блоки
с 1-го по 8-й соответственно), записанным в биты №№ 2,1,0 регистра
PCLATH.
3. Если в наличии имеются 2 страницы памяти программ, то выбор той
или иной страницы памяти программ определяется уровнем (0 или 1.
Страницы 1 и 2 соответственно), записанным в бит № 3 регистра
PCLATH.
4. Команды call и goto имеют 11-разрядную адресацию, и поэтому они
работают только в "границах" одной страницы памяти программ.
Той, которая задается в бите №3 регистра PCLATH.
Для того чтобы эти команды работали в "границах" той страницы
памяти программ, которая Вам нужна (необходимо организовать переход в
ПП, "лежащую" на другой странице памяти программ), необходимо, перед
исполнением любой из этих команд, соответствующим образом
скорректировать содержимое бита №3 регистра PCLATH (выбрать другую
страницу).
7
5. Если речь идет о комплексном выборе и страницы памяти программ, и
блока памяти программ, то нужно соответствующим образом
скорректировать содержимое битов регистра PCLATH с №№ 3,2,1,0.
Если для этого применяются бит-ориентированные команды, то
состояния тех битов, которые остаются неизменными, можно
не подтверждать.
6. Работа в пределах одной страницы памяти программ:
а) в случае, если ранее была отработана ПП вычисляемого перехода,
"лежащая" в одном блоке памяти программ, а далее "грядет" отработка
ПП вычисляемого перехода, которая "лежит" в другом блоке памяти
программ (с другим номером), то перед началом отработки ПП
вычисляемого перехода, "лежащего" в другом блоке памяти программ,
нужно скорректировать содержимое регистра PCLATH (установить в нем
адрес этого "другого" блока).
b) при работе с командами call, которые не имеют отношения к
вычисляемым переходам, а также и в случае, если при помощи этой
команды, происходит вызов ПП вычисляемого перехода, которая "лежит"
в том же блоке памяти программ, в котором "лежит" ПП вычисляемого
перехода, отработанная накануне, номер блока памяти программ
корректировать не нужно (обращаться к PCLATH не нужно).
с) при работе с командами goto, во всех случаях, номер блока памяти
программ корректировать не нужно (обращаться к PCLATH не нужно).
Работа в пределах двух страниц памяти программ.
d) то же самое, что в пункте 6a, но с учетом работы с битом №3
регистра PCLATH.
e) то же самое, что в пунктах 6b и 6c, но с учетом работы с битом №3
регистра PCLATH.

Все это конечно распрекрасно, но лучше один раз увидеть, чем 100 раз "протарахтеть".
Реализую эту "концепцию".
Примеры взяты из программы BP_9.asm.

Пример №1:

clrf PCLATH ; Выбор 1-го блока 1-й страницы.


call KNOPKA_DA ; Переход в ПП вывода на индикацию этой
; надписи.
;--> Возврат по стеку из ПП KNOPKA_DA.
bsf PCLATH,0 ; Выбор 2-го блока 1-й страницы.

Перед вызовом ПП KNOPKA_DA, работа происходила на 1-й странице памяти


программ, в блоке памяти программ, с номером, отличным от 1-го.
В ПП KNOPKA_DA, исполняется ПП вычисляемого перехода, "лежащая" в 1-м блоке
1-й страницы.
Поэтому, перед вызовом этой ПП, исполняется команда clrf PCLATH (выбор 1-го блока
1-й страницы).
PCLATH = 0000 0000.
В данном случае, оператор high применять нецелесообразно (зачем нужны 2 команды,
если можно обойтись одной?).
После возврата из ПП KNOPKA_DA, будет исполнена ПП вычисляемого перехода,
"лежащая" во 2-м блоке 1-й страницы.
Соответственно, исполняется команда bsf PCLATH,0 (выбор 2-го блока 1-й страницы, с
учетом того, что ранее был выбран 1-й блок 1-й страницы).
PCLATH = 0000 0001.

Пример №2:

clrf PCLATH ; Выбор 1-го блока 1-й страницы.


call MULTI ; Переход в ПП аварийной "пищалки".
;----> Возврат по стеку из ПП MULTI.
8
bsf PCLATH,3 ; Выбор 1-го блока 2-й страницы.

Перед вызовом ПП MULTI, работа происходила на 2-й странице памяти программ.


ПП MULTI "лежит" на 1-й странице памяти программ и в ней нет вычисляемого
перехода.
Поэтому, "блочные биты" (№№ 2,1,0) могут быть любыми.
Таким образом, в части касающейся ПП MULTI, значимо только то, что происходит
переход с одной страницы памяти программ на другую (со 2-й на 1-ю).
Значит, до вызова ПП MULTI, нужно изменить состояние бита №3 регистра PCLATH, с
1 на 0.
Это раз.
После возврата из ПП MULTI, которая "лежит" на 1-й странице, в дальнейшем, будет
исполняться ПП вычисляемого перехода, "лежащая" в 1-м блоке 2-й страницы.
Значит, без учета выбора номера блока, в бите №3 регистра PCLATH, нужно сменить
0 на 1.
Это два.
Вывод: перед вызовом ПП MULTI, выгодно применить команду clrf PCLATH (дешево и
сердито).
При этом, выбирается и нужная страница (1-я), и именно тот блок (1-й), который будет
нужен в дальнейшем (что-то типа предустановки).
А после возврата из ПП MULTI, нужно только скорректировать номер страницы
(bsf PCLATH,3), и все дела (1-й блок выбран ранее).
Это самый "короткий и изящный" вариант.
Оператор high применить конечно же можно, но в этом случае, команд будет больше.

Пример №3:

movlw high PAUSE_S; Выбор PCH 1-й команды ПП PAUSE_S


movwf PCLATH ; (находится на 1-й странице).
call PAUSE_S ; Задержка.
;----> Возврат по стеку из ПП PAUSE_S.
movlw high TEXT_26; Выбор PCH 1-й команды ПП TEXT_26
movwf PCLATH ; (находится на 2-й странице).

А это тот случай, когда при обеих коррекциях содержимого регистра PCLATH,
применение оператора high оправдано.
Исходные данные такие.
До вызова ПП PAUSE_S, PCLATH = 0000 1000 (в PCLATH установлен 1-й блок 2-й
страницы).
ПП PAUSE_S "дислоцируется" в 7-м блоке 1-й страницы (в PCLATH нужно выставить
0000 0110).
После возврата из ПП PAUSE_S, первая ПП вычисляемого перехода, которая будет
отработана по ходу исполнения программы (TEXT_26), "лежит" в 1-м блоке 2-й
страницы (в PCLATH нужно выставить 0000 1000).
То есть, до команды call PAUSE_S, имел место быть PCLATH = 0000 1000.
Для того чтобы ПП PAUSE_S была отработана "безглючно", перед вызовом ПП
PAUSE_S, нужно установить PCLATH = 0000 0110, а после возврата из ПП PAUSE_S,
для того, чтобы ПП TEXT_26 была отработана "безглючно", перед вызовом ПП
TEXT_26, нужно установить PCLATH = 0000 1000.
При таком "раскладе", выгодно воспользоваться оператором high и не "забивать себе
голову" всякими bcf/bsf/movlw/movwf, так как, от применения последнего, нет никакого
выигрыша.
А раз это так, то да здравствует комфорт.
Для того чтобы этот или другой вывод имел место быть, нужно, как минимум,
прикинуть что к чему (знать "подноготную", "руку набить"), а иначе, откуда взяться
объективному выводу?
Вот и вся "сермяжная суть/идеология" (понять легко, не легко "воплотить").
И еще один нюанс.
Вызов ПП TEXT_26 (call TEXT_26) может произойти не обязательно сразу же после
отработки того, что Вы видите выше, а "на каком-то удалении".
9
Хоть через 100 (условно) команд.
Если работа происходит в "границах" одной страницы памяти программ, то оператор
high должен быть "ориентирован" на название ПП, указанное в "рабочей" части
ближайшего (по ходу исполнения программы) вызова подпрограммы вычисляемого
перехода (call <название ПП>).
Естественно, при условии, что числовое значение PCLATH, необходимое для
"нормального функционирования" этой ПП, отличается от ранее установленного
значения PCLATH.
Если же таких отличий нет, то и "нечего огород городить".
То есть, если имеет место быть последовательная отработка группы
подпрограмм вычисляемых переходов, "лежащих" в одном и том же блоке
памяти программ и на одной и той же странице памяти программ, то
достаточно скорректировать содержимое PCLATH только "на влёте" в эту
группу, а далее, вплоть до окончания отработки этой группы,
корректировать содержимое PCLATH не нужно (зачем подтверждать то ранее
установленное состояние, которое и нужно?).
Сказанное есть дополнительное подтверждение рациональности размещения
подпрограмм вычисляемых переходов в составе "плотной группы", а не их
"раскиданности где попало", а заодно и подтверждение значимости элементарного
порядка.
Пример №4:

movf TermoP_L,W ; Нижний Т-порог -> W.


movwf Reg_3 ; и запись результата в Reg_3.
;================================================================================
; 2/10 преобразование (1х2) с перекодировкой результата.
;================================================================================
movlw high BIN2_10_T ; Выбор PCH
movwf PCLATH ; 1-й команды ПП BIN2_10_T.
movf Reg_3,W ; Reg_3 --> W.
call BIN2_10_T ; Переход в ПП 2/10 преобразования.
;--->Возврат по стеку из ПП BIN2_10_T
clrf PCLATH ; Выбор 1-го блока 1-й страницы.

Этот пример иллюстрирует тот случай, когда применение оператора high вынуждает
сначала сохранять содержимое W, подготовленное для 2/10 преобразования, в регистре
общего назначения Reg_3, а затем, после коррекции содержимого PCLATH,
восстанавливать "утраченное" (но мудро сохраненное) содержимое W (выделено синим
цветом).

Пример №5:

2-я страница памяти программ

TERMO На "влете": 0000 1ххх / ххх (не имеет значения) блок 2-й страницы.
........................
Есть команды call и goto
........................
movlw high TEXT_17; Выбор PCH 1-й команды ПП TEXT_17
movwf PCLATH ; (находится во 2 блоке 1-й страницы:
; 0000 0001).
call SL_I_POVIN ; Переход в ПП вывода на индикацию этой
; надписи.
;--> Возврат по стеку из ПП SL_I_POVIN.
bsf PCLATH,3 ; Выбор 2-й страницы.
На "вылете": 0000 1001 / 2-й блок 2-й страницы.
........................
........................
Возможно исполнение команды call, не связанной с вычисляемым переходом (один из
сценариев 1-го ветвления).
........................
........................
10
На "влете": 0000 1001 / 2-й блок 2-й страницы.
bcf PCLATH,0 ; Выбор 1-го блока 2-й страницы.
На "вылете": 0000 1000 / 1-й блок 2-й страницы.
........................
........................
На "влете": 0000 1000 / 1-й блок 2-й страницы.
clrf PCLATH ; Выбор 1-го блока 1-й страницы (0000 0000).
call MULTI ; Переход в ПП аварийной "пищалки".
;----> Возврат по стеку из ПП MULTI.
bsf PCLATH,3 ; Выбор 1-го блока 2-й страницы.
На "вылете": 0000 1000 / 1-й блок 2-й страницы.
........................
........................
На "влете": 0000 1000 / 1-й блок 2-й страницы.
movlw high PAUSE_S; Выбор PCH 1-й команды ПП PAUSE_S
movwf PCLATH ; (находится в 7-м блоке 1-й страницы:
; 0000 0110).
call PAUSE_S ; Задержка.
;----> Возврат по стеку из ПП PAUSE_S.
movlw high TEXT_26; Выбор PCH 1-й команды ПП TEXT_26
movwf PCLATH ; (находится в 1-м блоке 2-й страницы:
; 0000 1000).
На "вылете": 0000 1000 / 1-й блок 2-й страницы.
........................
........................
На "влете": 0000 1000 / 1-й блок 2-й страницы.
movlw high IND_TERMO; Выбор PCH 1-й команды ПП IND_TERMO
movwf PCLATH ; (находится в 7-м блоке 1-й страницы:
; 0000 0110).
call IND_TERMO ; Переход в ПП IND_TERMO.
;----> Возврат по стеку из ПП IND_TERMO.
movlw high TEXT_27; Выбор PCH 1-й команды ПП TEXT_27
movwf PCLATH ; (находится в 1-м блоке 2-й страницы:
; 0000 1000).
На "вылете": 0000 1000 / 1-й блок 2-й страницы.
........................
........................
На "влете": 0000 1000 / 1-й блок 2-й страницы.
movlw high IND_TERMO; Выбор PCH 1-й команды ПП IND_TERMO
movwf PCLATH ; (находится в 7 блоке 1-й страницы:
; 0000 0110).
call IND_TERMO ; Переход в ПП IND_TERMO.
;----> Возврат по стеку из ПП IND_TERMO.
;================================================================================
; Обеспечение необходимого времени "высвечивания" надписи.
;================================================================================
call PAUSE_S ; Задержка.
;----> Возврат по стеку из ПП PAUSE_S.
bsf PCLATH,3 ; Выбор 2-й страницы.
На "вылете": 0000 1110 / 7-й блок 2-й страницы.
........................
........................
Второе ветвление
btfsc Status,C ; Результат "+/=0" или "-"
; (порог превышен или нет) ?
Сценарий "закольцовки"
goto TERMO ; Если порог превышен, то ПП TERMO исполняется
; снова (с поднятым флагом срабатывания
; термозащиты).
Сценарий "программа исполняется далее"
........................
На "влете": 0000 1110 / 7-й блок 2-й страницы.
movlw high TEXT_28; Выбор PCH 1-й команды ПП TEXT_28
movwf PCLATH ; (находится на 2-й странице).
На "вылете": 0000 1000 / 1-й блок 2-й страницы.
........................
11
........................
На "влете": 0000 1000 / 1-й блок 2-й страницы.
movlw high PAUSE_S; Выбор PCH 1-й команды ПП PAUSE_S
movwf PCLATH ; (находится в 7-м блоке 1-й страницы:
; 0000 0110).
call PAUSE_S ; Задержка.
;----> Возврат по стеку из ПП PAUSE_S.
На "вылете": 0000 0110 / 7-й блок 1-й страницы.
return ; Возврат из ПП TERMO (на 1-ю страницу).

А это более сложный пример наиболее оптимальных (на мой взгляд), многократных
предустановок (коррекций) PCLATH, производимых во внутреннем цикле достаточно
"мощненькой" подпрограммы (made in КЕА).
В том числе и с учетом наличия классических, двухсценарных ветвлений, отработка
сценариев которых, связана с необходимостью предустановки PCLATH (не все
ветвления связаны с предустановкой PCLATH).
Пока и двух таких ветвлений достаточно, но их может быть и больше.
В данном случае, в "PCLATH-контексте", существенно то, что один из сценариев
первого ветвления предполагает исполнение команды call (см. выделенное зеленым
цветом).
По первому сценарию второго ветвления, происходит "закольцовка" на начало ПП
TERMO, а по второму сценарию, этой "закольцовки" не происходит, и "программа
исполняется далее".
Этот "PCLATH-мозгозаворот" работает так.
ПП TERMO "лежит" на 2-й странице памяти программ.
Все вызовы ПП TERMO происходят из 1-й страницы памяти программ.
Значит, "войти" в ПП TERMO нужно с заранее выбранной, 2-й страницей памяти
программ.
Что и происходит непосредственно перед вызовом (вызов происходит из 1-й страницы
памяти программ):
........................
bsf PCLATH,3 ; Выбор текущего блока 2-й страницы.
call TERMO ; Переход в ПП работы с датчиком.
;--> Возврат по стеку из ПП TERMO.
........................
После того, как это благое и необходимое дело свершится, можно не опасаться
"PCLATH-бяк" со стороны команд call (не связанных с вычисляемыми переходами) и
goto, отрабатываемых до первого (по ходу исполнения ПП TERMO) вызова ПП
вычисляемого перехода (см. пункт 6e "правил игры").
Примечание: в данном случае, такие команды есть.
По ходу исполнения ПП TERMO, первой отрабатывается ПП вычисляемого перехода
(TEXT_17), входящая в состав ПП SL_I_POVIN (вывод на индикацию надписи
СЛУШАЮСЬ и ПОВИНУЮСЬ!.
"Координаты" ПП TEXT_17: 2-й блок 1-й страницы.
Именно поэтому, перед вызовом ПП SL_IPOVIN, в PCLATHе и нужно "выставить эти
координаты". Что и имеет место быть (используется оператор high).
ПП SL_I_POVIN, кроме ПП TEXT_17, содержит в своем составе и аналогичную ПП
вычисляемого перехода с названием TEXT_18.
Обе они "лежат" во 2-м блоке 1-й страницы.
Поэтому, перед исполнением ПП TEXT_18, предустанавливать PCLATH не нужно
(теория - см. выше).
Возврат из ПП SL_I POVIN осуществляется из 1-й страницы (PCLATH,3 = 0).
Далее, страница изменяется (bsf PCLATH,3).
Причина: один из сценариев первого ветвления предполагает исполнение команды call,
не связанной с вычисляемым переходом (см. выделенное зеленым цветом).
Если, перед исполнением этой команды, не предустановить 2-ю страницу, то всем Вам
хорошо известная рабочая точка "улетит" не туда, куда нужно, а туда, "где Макар
телят не гонял" (в совсем не нужное "место" 1-й страницы, которое, кстати,
элементарно "вычисляется").
То есть, результатом исполнения этого сценария будет "двухсотпроцентный глюк".

12
Примечание: в данном случае, речь идет о команде call (не связанной с ПП
вычисляемого перехода), которая имеет отношение к ветвлению, но то же самое
относится и к командам call (не связанным с ПП вычисляемых переходов), которые не
имеют отношения к ветвлениям и к командам goto, которые или имеют, или не имеют
отношения к ветвлениям. Вот такая получается "свистопляска".
Короткий вопрос: "В чем причина этой изумительной/шокирующей неожиданности
(глюка)"?
Короткий ответ: в "глубочайше-сермяжном" смысле, заложенном в пункте 6е
"вышележащей, серенькой" таблицы (она хоть и невзрачная, но довольно-таки
премудрая).
Какая страница, на "вылете" из первой предустановки, установлена в PCLATH?
Первая (см. "дислокацию" ПП TEXT_17).
Чего "вожделеем"?
Исполнения "того-сего" (связанного с call/goto/пунктом 6e), "лежащего" на 2-й странице.
Ну и в чем дело? bsf PCLATH,3 (ОСОЗНАННО !!!), и все дела.
Именно так и "закаляется сталь".
А кто не поймет "сермяжного" (напоминаю про "12 стульев") смысла сказанного, тот
будет частенько напрягаться, "выковыривая рабочую точку из всяческих непотребных
мест" (типа "бардель"), коих великое множество.
Сказанное относится и ко всем остальным командам call/goto, подпадающими под пункт
6e (вся ПП TERMO "лежит" на 2-й странице памяти программ), просто я не стал
"разрисовывать" все эти call/goto по причине того, что ПП TERMO "совсем не хилая".
Сейчас, главное - понять общий принцип (стратегию) "делания PCLATH-дел".
В части касающейся пункта 6e, вне зависимости от того, есть ветвления
или их нет, этот принцип прост: команды call/goto должны исполняться
только при условии наличия в бите №3 регистра PCLATH того признака
страницы памяти программ (0 или 1), на которой "дислоцируются" эти
команды.
Еще раз напоминаю причину такого "расклада": команды call/goto работают только в
"границах" одной страницы памяти программ ("пересечь границу" страницы памяти
программ они не могут).
А именно, той страницы, которая, на момент начала исполнения этих команд,
установлена в бите №3 регистра PCLATH (в случае работы с двухстраничным ПИКом.
Если страниц больше, то задействуется и бит №4).
Можете в этом убедиться (см. выше): какие бы "PLATCH-катаклизмы" не происходили,
в конечном итоге, на выходе из коррекции содержимого регистра PCLATH, в его бите
№3, всегда устанавливается единица (для случая работы на 2-й странице памяти
программ).
Имеется несколько таких коррекций, что для "не хилой" подпрограммы, вполне
естественно и сильно удивляться этому не стОит.
Я не стал "расписывать" каждую из них, так как смысл этих коррекций одинаков.
Только вариации разные.
Сказанного и показанного выше, на мой взгляд, вполне достаточно для того, чтобы
разобраться со всеми этими, а также и прочими вариациями.
Остановлюсь только на 2-м ветвлении.
Если будет иметь место быть сценарий "программа исполняется далее", то опять же,
смысл "шевеления" прежний.
Если будет иметь место быть сценарий "закольцовки" на начало ПП TERMO, то "влёт"
в нее будет произведен с PCLATH,3 = 1, что и требуется.
Напоминаю, что первый "влёт" в ПП TERMO (с "аэродрома" 1-й страницы)
производится с PCLATH,3 = 1.
Возврат из ПП TERMO производится с PCLATH,3 = 0.
Это и нужно, так как в данном случае, все вызовы ПП TERMO производятся из 1-й
страницы памяти программ.
В части касающейся возврата, получилось удачно.
В случае же "неудачности" (возврат с PCLATH,3 = 1), перед возвратом из ПП TERMO,
нужно "принудительно" выставить PCLATH,3 = 0.

Теперь настал черед разобраться с еще одной разновидностью "наведения порядка".


13
Предположим, что в ходе текущей работы над текстом программы, программист
"уперся лбом" в "границу" между 1-й и 2-й страницей памяти программ.
Как быть далее?
Продолжить "ваяние" текста программы как ни в чём не бывало или подсуетиться?
В первом случае, "граница пройдет" через подпрограмму ("разрыв на 2 куска").
То есть, верхняя часть этой ПП будет "лежать" на 1-й странице, а нижняя ее часть -
на 2-й.
Причем, после любого "чиха", произведенного в каком-нибудь "месте" 1-й страницы,
вниз/вверх (зависит от конкретного "чиха") сместится не только содержимое 1-й
страницы (то, которое ниже "чиха"), но и всё содержимое 2-й страницы.
А если в том, что смещается, "дислоцируются" ПП вычисляемых переходов?
Да и вообще, зачем "бардак/геморрой" нужен? Не нужен он вообще. Даже даром.
После соответствующей активизации своей извилины, я, пришел к следующим
выводам.
На стадии работы с черновиками, нужно обеспечить "свободное местечко" и в 1-й, и
во 2-й странице памяти программ (обеспечение "свободы дальнейших маневров"), ведь
"кто её знает, что день грядущий нам готовит".
Со 2-й страницей все понятно - "свободного места завались".
А вот с 1-й страницей - не очень.
При "подходе к меже", "свободного местечка" явно маловато.
Значит, нужно его как-то обеспечить (подсуетиться/извилину поднапрячь).
За счет чего обеспечить?
За счет переноса "того-сего" ("передислокации") с 1-й страницы на 2-ю.
При этом, на стадии работы с черновиками, мелочиться не стОит.
Чтобы, на 1-й странице, "свободного местечка" было побольше, эффективнее всего
"передислоцировать" на 2-ю страницу не "кучу" мелких подпрограмм (с ними можно
запутаться), а какую-нибудь "мощненькую" подпрограмму.
В данном случае, с 1-й страницы на 2-ю, я перенес ПП TERMO. Целиком.
После этого, возникает вопрос о "судьбе" ее "обслуги".
Если та или иная "обслуга" используется только в "передислоцированной"
подпрограмме, то и проблем нет: она тоже переносится на 2-ю страницу ("в комплекте
c матерью").
С той "обслугой", которая будет вызываться и из 1-й, и из 2-й страницы, сложнее.
В этом случае, нужно заняться "бухгалтерией" и прикинуть "приход/расход".
Проще говоря, нужно ответить на вопрос: "Выгоден или не выгоден перенос, с 1-й
страницы на 2-ю, той или иной "обслуги", участвующей как в работе ПП TERMO, так и
в работе того-сего, лежащего на 1-й странице"?
Если выгоден, то перенос осуществляется, а если не выгоден, то нет.
Более подробно об этом будет рассказано в следующем подразделе.
Предположим, что "приход/расход" подсчитан, соответствующие выводы сделаны, и в
соответствии с этим, осуществлен перенос с 1-й страницы на 2-ю.
После этого, нужно озаботиться соответствующими предустановками PCLATH
("соблюсти формальности") и добиться работоспособности перенесенной подпрограммы,
в составе программы.
Во избежание бестолковки и лишней работы, переносить нужно ту подпрограмму,
которая ранее (до переноса) работала "так, как положено".
При таком "раскладе", ошибки в ее работе, имеющие место быть после переноса,
будут связаны только с неправильной организацией переноса.
Согласитесь со мной, что это гораздо менее "геморройно", чем в случае "наезда друг
на друга" ошибок различных функциональностей ("вполне адская смесь").
Вопрос: "Как технологически осуществить перенос того-сего с 1-й страницы на 2-ю"?
Ответ: сначала нужно перенести ПП TERMO в самый конец программы ("врезать"
перед директивой END).
С соответствующей "обслугой" или без нее (с ней можно разобраться после переноса).
После этого, все то, что "врезано", нужно как-то сместить на 2-ю страницу.
И не частично, а полностью.
Это делается при помощи директивы ORG, которую нужно "прописать" непосредственно
перед "верхушкой произведенной врезки".
Я "прописал" ORG 801h.
14
То есть, 1-я команда "врезки" будет "дислоцироваться" в 2050-й ячейке памяти
программ (в начале 2-й страницы).
Можно "уйти" и на ORG 800h (2049-я ячейка), но я десятичный нолик люблю (он
симпатичнее девятки).
В любой момент, это смещение можно скорректировать.
Что получилось?
Получилось четкое разделение программы на страницы (в PC), что и есть одна из
составляющих порядка.
Между последней командой той части программы, которая "лежит" на 1-й странице, и
первой командой той части программы, которая "лежит" на 2-й странице, образовался
"ефрейторский суперзазорище" (в тексте программы не виден, но четко виден в окне
ROM), в который можно поместить много кое-чего.
Именно в этом и состоит "коварство замысла", ведь программа находится на стадии
разработки и вполне может возникнуть необходимость "расширения и углубления" того,
что "лежит" на 1-й странице (а там "лежит МАТКА"!).
Если имеется "ефрейторский суперзазорище", то в части касающейся работы на 1-й
странице, "руки развязаны".
А именно, при таком "раскладе" (применение директивы ORG), любое (в пределах
дозволенного) увеличение объема той части программы, которая "лежит" на 1-й
странице, не приведет к смещению вниз той части программы, которая "лежит" на 2-й
странице.
Просто, по мере роста объема той части программы, которая "лежит" на 1-й странице,
"ефрейторский суперзазорище" будет постепенно уменьшаться.
Но это уменьшение должно производиться только в пределах дозволенного.
В том смысле, что за 2048-ю ячейку PC "заходить" нельзя, а иначе будет большое
"несчастье".
Таковы "правила игры", частично задаваемые очень даже симпатичной директивой ORG
Если на момент окончания работы над программой, "ефрейторский суперзазорище"
сократился, но все-таки имеет неустраивающую Вас "массу" (кстати, под его
организацию, расходуется "моторесурс" PC !), значит нужно "мухлевать".
Например, перенести какой-то подходящий (по "массе") "кусок" программы из 2-й
страницы в 1-ю, не забывая при этом о PCLATHе.
Если в дальнейшем выяснится, что "ефрейторский суперзазорище" оказался
маловатым, то нужно перенести какой-то подходящий (по "массе") "кусок" программы из
1-й страницы в 2-ю, опять же, не забывая при этом о PCLATHе.

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


нет: изначально, есть пастух и одно большое суперстадо, в котором все перемешалось
(короче, бардак).
Пастух, при помощи кнута, а также и своего профессионализма/идейности, должен
раскидать всю эту братию по отдельным стадам и загнать эти стада в отдельные
загоны (и пастбища тоже отдельные). На то он и пастух.
Если сумеет, то каждый день будет кушать хлеб с маслом и икоркой, а если не
сумеет, то будет черствая корка хлеба (раз в неделю).
Вот и весь жизненный смысл, детально уяснить который Вы сможете в следующем
подразделе.
Будет предоставлена "живая" программа BP_9.asm.
В ней, наряду с практической реализацией сказанного, организован дополнительный,
"интеллектуальный" подрежим установки температурных порогов пользователем
("шаг" - 1 градус).
"Интеллектуальный" в том смысле, что "железяка" принципиально не допустит как
выхода за разумные границы диапазона установки этих порогов (разумность
определяет программист), так и ошибок пользователя при назначении верхнего и
нижнего температурных порогов.
Плюс, при этом, она еще и симпатично (на мой взгляд) "попискивает" (и не абы как, а
по делу) и EEPROM-запоминает установленное.

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

15

Вам также может понравиться