|
|
Материалы для книги Ко мне, как к автору книги постоянно поступают различные замечания от читателей. Все такие замечания я внимательно изучаю. Многие такие письма помогли мне обнаружить различные досадные ошибки, которые я обязательно учту при переиздании книги. Но иногда письма вызваны тем, что материал, изложенный в книге оказался непонятным для читателя. В таких случаях в ответном письме я стараюсь более подробно объяснить непонятный момент. Если читателю не понятно - это недостаток моей книги. Значит я плохо объяснил. Я решил помещать такие поснения на этом сайте, что бы каждый желающий мог найти здесь ответы на все возникающие вопросы. Сегодня я помещаю ответ на вопрос одного из самых активных моих читателей из молдавии. |
Переменные и константы Письмо:
Ну давайте разберемся. В любой программа применяются переменные и константы. Константа - это некое фиксированное значение (число), которое обычно определяется в начале программы и применяется в программе далее в одном или нескольких разных местах. Например, вы можете задать код каждой клавиши при помощи константы. Допустим, у вас есть десять клавиш. Вы можете ввести десять констант: Kl1, Kl2, Kl3, Kl4, Kl5, Лl6, Kl7, Kl8, Kl9 и Kl10. В начале программы вы присваиваете им значения кодов клавишь. Я возьму коды произвольно. Просто для примера. Допустим это будет так: Kl1 EQU 31 ; константе Kl1 присваиваем значение 31 Затем, в тексте программы везде, где нужно использовать код клавиши,
можно поставить имя соответствующей константы. Если вы всегда будете ставить
именно имя константы, то, во первых, программа станет более читаемой.
В самом деле. Если вы встретите команду "Записать в ячейку памяти
число 31" будет не понятно - это вы записываете код клавиши, или
какую либо другую величину. А если команда будет звучать так: "Записать
в ячейку памяти константу Kl1", то тут не нужны никакие комментарии.
И второе преимущество. Предположим, вы решили изменить схему вашего устройства.
При изменении схемы поменялись коды всех клавиш. Естественно, вам придется
поменять программу. Однако, в том случае, если вы использовали константы,
эта задача не вызовет никаких затруднений. Вам нужно лишь поменять значение
констант лишь в одном месте - в начале программы, где константам присваиваются
какие либо значения. Если же в тексте программы вы вместо констант использовали
коды, то вам придется перелопатить всю программу (а реальные программы
могут занимать до несколько сотен строк). И найти все места, где используются
коды клавиш. Это осложняется еще и тем, что встретив код 31, вы еще должны
разбираться, а действительно ли это код клавиши, или это что то другое. Теперь о специфике языка Ассемблера. Ассемблер - это машинно-ориентированный
язык. По сути, это описание системы команд конкретного процессора. А система
команд процессора не оперирует с такими понятиями, как константа или переменная.
Процессор работает с командами и ячейками. Оджнако Ассемблер имеет и константы
и переменные. Как это совмещается? А очень просто. Константа - это исключительно
конструкция языка. После трансляции программы мы увидим только коды. И
от имен Kl1, Kl2 и т. д. не останется и следа. cjne a,#Kl1,M1 Которая означает "Если содержимое аккумулятора равно константе Kl1, перейти по метке M1. После трансляции этой строки программы, в коде программы появится следующие три байта: B4 1F 12 (все числа в шестнадцатеричной форме) Где B4 - это код операции cjne a,#data,addres Переменная, с точки зрения Ассемблера, имеет другой смысл. Переменные в процессе выполнения программы могут принимать различные значения. Эти значения нужно где то хранить. В описываемом микропроцессоре для хранения разных чисел имеется целый набор регистров, а так же 128 внутреннего ячеек ОЗУ. Переменную можно хранить в любой из этих ячеек. Определение переменной - это определение регистра или ячейки ОЗУ, где она будет храниться. Например, если коды ваших клавишь будут меняться в процессе работы программы (случай не очень вероятный, но для примера сойдет), то коды клавиш можно было бы разместить в ячейках ОЗУ. Например, код первой клавиши можно поместить в ячейку ОЗУ с адресом 31, код второй клавиши, в ячейку 32 и т.д. Обратите внимание на то, что я выбрал одни и те же значения для констант (в первом примере) и для адресов ячеек (во втором). Я сделал это намеренно, что бы показать, что одни и те же цифры могут означать совершенно разные вещи. Но это вовсе не обязательно. Адреса ячеек можно выбирать любые в пределах адресного пространства микроконтроллера. Если коды клавиш - это переменные и мы будем хранить их в ячейках памяти, то нам нужно в начале программы сначала определить переменные Kl1, Kl2, Kl3 и т. д. Их можно определить точно так же, как и константы. Просто те же команды (см. выше) При этом за символьным обозначением Kl1 закрепится число 31, За Kl2 - число 32 и так далее. Точно так же, как и в первом случае. Разница будет только в том, что использовать эти числа мы будем по разному. Теперь это будут адреса ячеек памяти. Далее, программа, в процессе своей работы должна записать в каждую эту ячейку код клавиши. С точки зрения языка, это будет означать - присвоение переменной начального значения. Сделать это можно при помощи следующих команд: mov Kl1,#131 ; Записать в ячейку Kl1 число 131 Как видим, для понятности я применил другие коды для клавиш. Ну а теперь посмотрим, как будет выглядеть команда, проверяющая код клавиши Kl1, аналогичная предыдущему случаю для случая, когда код клавиши хранится в переменной. На языке Ассемблера она будет выглядеть следующим образом: cjne a,Kl1,M1 Как видим, в этой новой команде у второй константы отсутствует символ #. Этот символ имеет смысл признака непосредственных данных. Если в команде на языке ассемблера перед числом или символьным идентификатором стоит этот символ, то данное число - непосредственно данные. Как в предыдущем примере. Там содержимое аккумулятора сравнивается с числом Kl1 (то есть с числом 31). Сдесь же содержимое аккумулятора сравнивается с содержимым ячейки памяти, которая имеет адрес Kl1 (то есть адрес 31). А в этой ячейке у нас хранится число 131 (код клавиши). После трансляции этой команды в программном коде появятся следующие три числа: B5 1F 12 (все числа в шестнадцатеричной форме) В этом случае B5 - это код команды. Теперь это другая команда.
Команда, работающая с ячейкой памяти а не с константой. В общем виде эта
операция записывается так cjne a,direct,addres Именно в этом суть фразы, которую вы посчитали неправильной: "Константа - это адрес ячейки памяти, а переменная это значение, хранящееся в этой ячейке". Константа может иметь самый разный смысл. Это может быть и код для проверки (код клавиши) и какой то коэффициент, и адрес ячейки памяти и любое числовое значение. В том конкретном случае - константой обозначен адрес ячейки памяти, где хранится значение переменной. Возможно, в книге я плохо это объяснил. С вашего разрешения я помещу весь текст этого письма на сайт, посвященный моим книгам http://book.mikroprocessor.by.ru .
Тут нет ничего противоположного. Константа count - это адрес ячейки памяти, где хранится значение счетчика. Программа изменяет это значение в процессе работы. Приведенные два примера показывают как используется символ #. Если вам нужно загрузить в аккумулятор содержимое этой ячейки, мы пишем mov a,count. Если вам для чего-то потребуется обрабатывать сам адрес ячейки. Например, прибавить к адресу ячейки смещение для того, что бы извлечь значение из ячейки, отстоящей на заранее определенном расстоянии от исходной, то применяется команда mov a, #count. Например, если константа count равна 30, то команда mov a, count запишет в аккумулятор содержимое ячейки с адресом 30. А команда mov a, #count запишет в аккумулятор число 30. В данном случае - это адрес ячейки. Но это знаете только вы - программист. Для микроконтроллера, это просто число 30. Вот такие объяснения :) -- |