Конспекты лекций. Конспект лекций. Микропроцессорные устройства систем управления
Скачать 0.73 Mb.
|
4.3. Примеры написания программ.Рассмотрим примеры написания простейших фрагментов, которые могут встретиться в программе. При разборе примеров будем пользоваться условными регистрами: A – аккумулятор; B, C, D, E, H, L – регистры общего назначения, которые могут объединяться в регистровые пары BC, DE, HL. Причем регистровая пара HL будет выполнять функции адресного указательного регистра, т.е. регистра, указывающего на адрес (содержащего адрес) ячейки памяти M, к которой идет обращение в данной команде при косвенной регистровой адресации. Такой синтаксис заимствован из языка Ассемблера МП Intel8080. Пример 1. Проверить состояние третьего разряда регистра B. Если значение этого разряда равно 1, то выполняется следующая по программе команда. В противном случае выполняется команда, адрес которой 00АА16. Решение. Для микроконтроллеров, представляющих собой функционально полную МП-систему, реализованную в одном кристалле микросхемы, как правило, характерно наличие в системе команд специальных команд побитовых операций. С их помощью можно выделять определенные биты, записывать в них нули, единицы, инвертировать их значения. Многие МП таких команд не имеют. Но это не значит, что операции над отдельными битами для них неприемлемы. Для выделения каких-либо разрядов имеющегося байта выполняется операция поразрядного маскирования, с помощью которой из рассмотрения исключаются не интересующие нас разряды. В даннмо случае маскирование производится путем поразрядного логического умножения исходного байта на маску, в качестве которой используется набор битов, равных нулю во всех разрядах, кроме проверяемого третьего. Очевидно, что результат умножения будет равен или не равен нулю в зависимости от того, равно или не равно нулю значение проверяемого разряда исходного байта. Таким образом, представленная задача решается путем выполнения следующей последовательности операторов:
Пример 2. Не изменяя значений остальных разрядов, записать единицы в первый и второй разряды, ноль в пятый разряд и изменить на противоположное значение шестого разряда содержимого ячейки памяти с адресом A5C216. Решение. Очевидно, что при поразрядном логическом сложении исходного байта и маски, значения тех разрядов исходного байта, в которых маска содержит нули, не меняются, а тех разрядов исходного байта, в которых маска содержит единицы, станут равными единице. Для записи нуля в интересующие разряды исходного байта необходимо, как и в предыдущем примере, логически умножить этот байт на маску с нулями в этих разрядах. При выполнении поразрядной логической операции ИСКЛЮЧАЮЩЕЕ ИЛИ над исходным байтом и маской, значения тех разрядов исходного байта, в которых маска содержит нули, не меняются, а значения остальных разрядов изменятся на противоположные. Поскольку в программе придется три раза подряд выполнить логические операции над исходным байтом и соответствующими масками, результаты которых будут каждый раз фиксироваться в аккумуляторе, то целесообразно исходный байт поместить в регистр-накопитель аккумулятор, а выполнять логические операции с помощью команд прямой адресации над содержимым аккумулятора и задаваемых в командах в качестве операндов масок. Модификацию необходимо выполнить над содержимым ячейки памяти. Как мы договорились, это содержимое поместим в аккумулятор. В аккумуляторе сформируется и результат последней выполненной команды. Но по условию изменить надо содержимое ячейки памяти, т.е. результат нужно будет из аккумулятора переслать обратно в ячейку памяти. Таким образом, необходимо будет дважды обратиться к одной и той же ячейки памяти. В тех случаях, когда необходимо многократно обращаться к ячейке памяти с одним и тем же адресом подряд, или адрес ячейки памяти меняется по определенному закону, например инкрементируется или дикрементируется при каждом обращении, удобно использовать косвенную регистровую адресацию. Это позволяет повысить время выполнения программы, один раз задав адрес в указательный адресный регистр, а само обращение к памяти выполнять с помощью быстрых однобайтовых команд косвенной адресации. В принятых нами обозначениях такая адресация реализуется путем обращения к ячейке памяти M как к внешнему регистру, адрес которой указывается регистровой парой HL. Поставленная задача может быть решена следующей последовательностью команд:
Пример 3. Содержимое предварительно обнуленного регистра B увеличивать на единицу до тех пор, пока оно не станет равным содержимому регистра C, после чего перейти к выполнению дальнейшей программы. Решение. Очевидно, что для решения поставленной задачи необходимо организовать циклический процесс, на каждом шаге которого будет выполняться инкрементирование содержимого регистра B и сравнение его текущего значения с содержимым регистра C. Как только содержимые этих регистров сравняются, будет осуществлен выход из цикла. Для установления факта равенства необходимо использовать команду сравнения. Пока не будет иметь место равенство, разница содержимых этих регистров будет не нулевой, т.е. признак нуля регистра флагов будет иметь нулевое значение. В этом случае необходимо будет перейти к следующему шагу цикла, сославшись на метку первой команды тела цикла командой условного перехода по отсутствию нулевого результата. Как только команда сравнения даст нулевой результат вычитания содержимых регистров B и C, условие ненулевого результата не выполнится и цикл будет завершен. Текст программы может выглядеть следующим образом:
Пример 4. Обнулить 50 ячеек памяти в сторону уменьшения их адресов, начиная с ячейки с адресом 800016. Решение. Как и в предыдущем примере, очевидно, что в данном случае нет необходимости обнулять все 50 ячеек памяти, напрямую адресуясь к ним пятидесятью командами прямой адресации. Удобнее всего организовать цикл из пятидесяти шагов, записывая в каждом шаге цикла в ячейку памяти, как во внешний регистр M, ноль, косвенно адресуясь к ней через содержимое указательной регистровой пары HL. Предварительно в HL заносится адрес 800016 первой ячейки и далее содержимое HL уменьшается на единицу, формируя, таким образом, адрес текущей обнуляемой ячейки в текущем шаге цикла. Для того, чтобы проконтролировать количество шагов цикла, необходимо организовать счетчик. В качестве счетчика можно использовать любой свободный регистр общего назначения, начальное содержимое которого будет равно количеству шагов цикла – 50. Далее на каждом шаге цикла содержимое этого регистра будет дикрементироваться на единицу. Цикл будет повторяться до тех пор, пока содержимое счетчика шагов цикла не станет равным нулю. В качестве условия перехода в начало тела цикла можно использовать, таким образом, ненулевой результат дикремента счетчика шагов цикла. Фрагмент программы может иметь следующий вид.
Задача 5. Написать программу, постоянно опрашивающую порт ввода 1, на четыре младших разряда которого поступает двоично-десятичный код, и выводящую соответствующую этому коду десятичную цифру на семисегментый индикатор, подключенный к порту вывода 2. Решение. Прежде чем составлять программу, необходимо определиться: к каким разрядам порта вывода 2 будут подключены соответствующие сегменты семисегментного индикатора. Семисегментный индикатор имеет обозначение своих сегментов и выбранное подключение к разрядам порта вывода, как это показано на рис. 4.3. Рис.4.3. Подключение семисегментного индикатора к разрядам порта вывода. При выбранном подключении, приняв, что соответствующий сегмент индикатора светится при подаче на него логической единицы, между двоичными кодами индицируемых цифр и байтами на выходе порта (семисегментными кодами) должно быть соответствие, приведенное в табл.4.3. Воспользуемся следующим приемом: поместим в десяти последовательно расположенных вслед за программой ячейках памяти семисегментные коды в том порядке, в каком они приведены в табл.4.3. Адресу первой из этих ячеек присвоим метку TABL. Таким образом, в ячейке памяти с адресом TABL будет храниться семисегментный код цифры 0, в ячейке памяти с адресом TABL+1 – семисегментный код цифры 1 и т.д. Поместим адрес, соответствующий метке TABL, в регистровую пару HL. Если теперь к содержимому регистровой пары HL прибавить двоично-десятичный код индицируемой цифры, то, очевидно, что в результате образуется адрес той ячейки памяти, в которой хранится семисегментный код индицируемой цифры. Если вывести теперь код из этой ячейки памяти, используя косвенную регистровую адресацию, в порт вывода 2, будет обеспечено свечение десятичной цифры, соответствующей входному двоичному коду. Ниже приведена программа, выполняющая поставленную задачу.
*Примечание. Оператор DB относится к так называемым директивам (или псевдокомандам) языка ассемблера. Подобные команды не имеют машинных кодов, а служат для указания уточнений программе транслятору - ассемблеру. В данном случае директива DB размещает в последовательных ячейках памяти, начиная с ячейки, имеющей адрес, соответствующий метке TABL, последовательность семисегменных кодов. При трансляции исходной программы в объектную ассемблер заменит директиву DB последовательностью необходимых машинных команд, выполняющих эту операцию. Таблица 4.3. Соответствие десятичных цифр, двоично-десятичных и семисегментных кодов.
Пример 6. Из чисел, хранимых в 120 последовательных ячейках рамяти, начиная с ячейки с адресом 01A616, подсчитать количество тех чисел A, удовлетворяющих условию: 10A50. Результат подсчета вывести в порт вывода 7. Решение. Очевидно, что для решения данной задачи требуется реализовать операции сравнения и в зависимости от результата сравнения выполнить условный переход в нужное место программы. Т.к. число A может иметь 120 значений, то необходимо организовать цикл из 120 шагов. При решении задачи сначала проверяется принадлежность числа A верхней границе интервала, а затем нижней в каждом шаге цикла. И только если число A попадает в заданный интервал, то факт такого попадания подсчитывается в счетчике. В противном случае значение счетчика в данном шаге цикла остается неизменным. Результат подсчета и есть количество чисел A, удовлетворяющих требуемому нестрогому неравенству. Текст программы приводится ниже.
|