Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Эрни Каспер Программирование на языке Ассемблер...doc
Скачиваний:
120
Добавлен:
09.11.2019
Размер:
954.88 Кб
Скачать

2.Директивы ассемблера для микроконтроллеров семейства i8051

2.1.Общие понятия о процессах трансляции и компоновки

Приведенные в предыдущей главе команды могут быть переведены с языка Ассемблера в машинные коды микроконтроллера и далее в исполняемую программу при помощи двух программ, называемых транслятором и компоновщиком. Отложив до следующей главы вопрос о том, каким образом можно воспользоваться этими программами, рас­смотрим возможности управления процессами трансляции и компоновки при помощи операторов исходного текста. При разработке программы на Ассемблере необходимо дать задание не только микроконтроллеру, но и транслятору с компоновщиком. Поэтому в Ассемблере существует два вида операторов: команды, которые превращаются транслятором в машин­ные коды, и директивы, в которых даются задания на трансляцию и компоновку. В отличие от команд директивы могут состоять из нескольких строк, то есть быть составными. Область действия таких директив заключена между открывающей и закрывающей строками. Часть директив также переводится транслятором в машинные коды или влияет на них, а некоторые директивы используются только для удобства работы программиста и потому без них в принципе можно обойтись. В отличие от ассемблерного программирования для компьютеров, когда нужно позаботиться еще и о взаимодействие программы с операционной системой, для микроконтроллеров такой проблемы нет. Но это не облег­чает, а усложняет работу программиста, так как он должен сам решать вопросы взаимодействия программы с внешней средой.

Написание и отладка программ содержит творческую и рутинную компоненты. Рутинная часть работы может быть автоматизирована настолько, насколько удается формализовать ее. Для того чтобы ассемблер и компоновщик могли выполнить формализуемую часть работы по переводу исходного текста программы в машинный код, программист должен включить в него директивы. Директивы являются средствами управления ассемблером и компоновщиком, каждый из которых, с одной стороны, достаточно "умен" (интеллекта в них ровно столько, сколько заложено разработчиками программного обеспечения), чтобы обходиться без мелочной опеки программиста, а с другой - вполне управляем. В Ассемблере директивы позволяют определять и использовать дополни­тельные программные объекты, не предусмотренные архитектурой про­цессора. Но они должны быть определены так, чтобы транслятор мог реализовать их имеющимися в микроконтроллере средствами.

Преобразование исходного текста в машинный код осуществляется в три этапа. Сначала этот текст должен быть записан в файл с расширени­ем ASM при помощи обычного текстового редактора, не добавляющего никаких форматирующих символов. Затем текст нужно обработать транс­лятором, который в случае нарушения синтаксических правил выдает сообщения о местонахождении и типе каждой из ошибок. Если ошибок нет, то транслятор формирует объектный файл с расширением OBJ, а также, по желанию программиста, формирует файл протокола трансляции (листинг) с расширением LST. Объектный файл используется редактором связей (компоновщиком) для создания исполняемой программы, имеющей расширение TSK. Поскольку на каждом из этапов работы могут обнару­житься ошибки, приходится возвращаться назад для коррекции исходного текста. И только после получения машинного кода можно приступать к отладке программы.

Для того чтобы понимать сообщения транслятора и компоновщика об ошибках, нужно усвоить общие понятия о процессах трансляции и компоновки и о действиях, производимых транслятором и компонов­щиком по директивам в исходном тексте. Знание принципов трансляции и компоновки существенно облегчает освоение разных диалектов Ассемблера, соответствующих особенностям как архитектуры процессо­ров, так и математического обеспечения разработки разных фирм.

Упомянутый выше листинг является текстовым файлом, предназна­ченным для программиста. В нем приводится не только исходный текст, но и полученный машинный код в текстовом представлении. Для пред­ставления о задачах, решаемых при переходе от символического языка к машинному коду, рассмотрим листинг трансляции исходного текста на примере простой ассемблерной программы вычисления наибольшего общего делителя (НОД) двух положительных чисел по алгоритму Евкли­да. Он предписывает сначала разделить одно число на другое. Если остаток от деления равен нулю, то делитель является НОД. В противном случае нужно использовать в качестве делимого старый делитель, а в качестве делителя — остаток, и вернуться к операции деления.

Пусть два положительных числа (не превышающие 255) записаны в накопитель и регистр В. Тогда программа вычисления НОД может быть составлена всего из 3 команд. Эти команды работают в цикле, по выходе из которого искомое число будет находиться в регистре В. Лаконичность программы и отсутствие адресации к ОЗУ облегчают понимание меха­низма трансляции. Рассмотрим фрагмент листинга, представляющий результат трансляции программы:

1 0000 84 euclid: DIV АВ ; деление

2 0001 С5 FO ХСН А, В ; перестановка частного и остатка

3 0003 70 FB JNZ euclid ; возврат по ненулевому остатку

В самом листинге нет выделения ни жирным шрифтом, ни подчеркиванием, добавленных в этом примере автором. Жирный шрифт использован для показа исходного текста программы, который транслятор берет из файла с расширением ASM. А подчеркиванием выделены машинные коды команд, которые транслятор записывает в файл с расширением OBJ. В приведенном примере нет ни одной директивы. Но это не значит, что полноценную программу можно написать без директив. Отсутствие директив не приводит к тому, что транслятор и компоновщик работают "без руля и без ветрил". В начале их работы устанавливаются режимы "по умолчанию".

Как видите, результат трансляции программы представлен тремя группами столбцов. Первая колонка содержит десятичные номера строк исходного текста. Во второй колонке записаны шестнадцатеричные адреса команд в двухбайтовом формате. В последней группе колонок представлены байты машинных кодов команд в шестнадцатеричном виде., Примерно таким же образом записывались когда-то адреса и команды в стандартных бланках при программировании в кодах. Приращения адресов при переходе от строки к строке равны количеству байтов, отво­димых для хранения соответствующих данных и команд. Убедиться

в соответствии кодов операций и способов адресации операндов мнемо­нической записи команд в исходном тексте можно при помощи перечня команд, приведенного в Приложении 1. Для первой и третьей команд транслятор выбрал коды операции однозначно по мнемокодам исходного текста, а для второй команды пришлось сделать выбор из 11 вариантов, имеющих один и тот же мнемокод, в соответствии со способом адресации второго операнда к функциональному регистру. Адресная часть второй команды выбрана по имени регистра В. Имя операнда третьей команды задано программистом, что несколько усложнило работу транслятора в части вычисления адресного бита команды. Это имя (euclid) было определено в поле метки первой команды, поэтому ему был поставлен в соответствие адрес 0. Для вычисления адресной части команды услов­ного перехода транслятором использованы числовые значения адресов. После чтения управляющей команды содержимое программного счетчика будет равно 5, так что для возврата к началу программы нужно записать в ее адресной части -5, что в шестнадцатеричном коде байтового формата равно FBh.

Для обработки имен программных объектов транслятор ведет таблицу соответствия символических имен в исходном тексте программы их фактическим адресам. Эта таблица также выводится в листинг как текст:

Defined

Symbol Name

Value

References

Pre

BSECT

0000

Pre

CODE

0000

Pre

DATA

0000

1

euclid

0000

3

Pre

RSECT

0000

В первой колонке таблицы приводится номер строки, в которой определено символическое имя, во второй — само имя, в третьей — соответствующий ему адрес и в четвертой — список номеров строк, в которых имеются ссылки на это имя. Имена упорядочены по алфавиту. В таблицу вошли четыре имени, которые отсутствуют в исходном тексте. Это стандартные имена секторов программы, поэтому в первой колонке таблицы для них вместо номера строки записано Pre (от predetermined — предопределено). Если попытаться прочитать объектный файл при помощи текстового редактора в системе MS DOS, то из последовательности кодов 84 С5 FO 70 FB наверняка можно увидеть только букву "p" (латинскую строчную букву) вместо 70, а вид остальных символов будет зависеть от загруженной кодовой страницы. В частности, для кодовой страницы 866 (Россия) вместо 84 на дисплей выводится символ псевдографики (прямой угол с вершиной слева внизу), вместо С5 — буква "e", вместо FO — буква "П" и вместо FB — буква "Ш". Кроме того, как будет показано в следующей главе, объектный файл содержит большое количество информации, необходимое компоновщику и совершенно не нужное программисту. Так что эти пять кодов нужно еще суметь найти в объектном файле. Из приве­денного примера видно, насколько удобен листинг в части представления информации о результатах трансляции в текстовом формате.

Мнемокоды директив не совпадают с мнемокодами команд, но про­граммисту желательно иметь бросающееся в глаза различие между ними. Поэтому для удобства чтения программ лучше начинать мнемокод дирек­тивы с точки (это допускается синтаксическими правилами транслятора семейства i8051). Многие директивы имеют синонимы, то есть директивы с разными мнемокодами обозначают одно и то же. В этом случае в качестве основного мнемокода приводится тот, который используется в других диалектах Ассемблера. Для того чтобы читатели могли изучать исходные тексты авторов, использующих разную запись директив, приводятся синонимы основного мнемокода.

А теперь приведем две простейшие директивы. Первая из них

.END

По этой директиве транслятор прекращает трансляцию. В следующей за этой строкой части исходного текста можно писать все что угодно, ибо транслятор не читает далее ни строчки. Обычно трансляторы разрабаты­ваются для работы не с одним типом процессора, а со всем семейством. Для микроконтроллеров семейства i8051 выбор типа производится директивой .

.CHIP тип

По умолчанию этой директивой производится ассемблирование для типа 8051.