Александр Микушин - Занимательно о микроконтроллерах стр 54.

Шрифт
Фон

Многомодульные программы

Как это обсуждалось в предыдущей главе, разбиение исходного текста программы на отдельные модули делает его более понятным для программиста или нескольких программистов, участвующих в создании программного продукта. Язык программирования ASM-51 позволяет писать многомодульные программы. Однако каждый модуль программы должен быть оформлен соответствующим образом.

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

В языке программирования ASM-51 для этой цели используется директива public (общедоступные). Директива может быть использована в любом месте исходного текста модуля, однако обычно она размещается в его начале. Имена переменных в этой директиве перечисляются через запятую. Если в результате получается слишком длинная строка, то можно использовать несколько таких директив. Глобальное имя может быть объявлено только в одном модуле программы. Несколько глобальных переменных или подпрограмм с одним и тем же именем недопустимы.

Пример использования директивы public на языке программирования ASM-51:

PUBLIC Buflnd, Parametr

PUBLIC Podprogr,?Podprogr?Byte

Для ссылки на переменную или метку, объявленную в другом модуле, используется директива extrn. Идентификатор в пределах одного модуля не может быть одновременно объявлен как public и как extrn. В директиве extrn перечисляются через запятую имена подпрограмм и переменных, числовое значение которых редактор связей должен получить из других модулей и модифицировать все команды, в которых эти метки или переменные используются. Кроме того, для правильного использования инструкций микроконтроллера в директиве extrn должен быть указан тип памяти (data, bit, code, idata или xdata), в которой расположена переменная или метка. Для передачи числовых констант между модулями можно воспользоваться вспомогательным словом number Директива extrn может располагаться в любом месте исходного текста модуля. Идентификатор внешнего имени не может быть переопределен в программном модуле каким-либо способом. Рекомендуется с целью оптимизации результирующего объектного кода (в частности, команд JMP и CALL) размещать директиву EXTRN до ссылки на соответствующее внешнее имя (как правило, в начале исходного текста программного модуля или программного сегмента). Пример использования директивы extrn на языке программирования ASM-51:

EXTRN DATA (Buflnd, ERR), CODE (ASC_BIN, BIN_ASC), NUMBER (LIMIT)

EXTRN CODE (Podprogr)

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

Файл-заголовок на языке программирования asm-51 записывается на диск с расширением *.inc (сокращение от английского слова include - включать) и включается в исходный текст программы при помощи директивы include. Например:

$INCLUDE (REG51.INC)

При работе с пакетом программ, поставляемым фирмой keil, программа-транслятор с языка программирования ASM-51 "понимает" и файлы-заголовки, написанные для языка программирования С-51. Поэтому можно воспользоваться и этими файлами. Например:

#include <at87f51rc.h>

$include (init.inc)

Теперь рассмотрим команды редактора связей, которые позволят объединить несколько объектных модулей в один. В простейшем случае для объединения модулей можно использовать имя программы-редактора связей с необходимыми ключами. Для объединения нескольких модулей в исполняемую программу имена всех модулей передаются в редактор связей ri5i.exe в качестве параметров при запуске этой программы.

Приведем пример вызова редактора связей из командной строки DOS для объединения трех модулей:

r151.exe progr.obj, modul1.obj, modul2.obj

В результате работы редактора связей в этом примере будет создан исполняемый модуль с именем progr. Формат записи информации в этом файле остается прежним - объектным. Это позволяет объединять модули по частям, т. е. при желании можно из нескольких мелких модулей получить один более крупный.

В настоящее время часто пользуются интегрированными средами программирования, например, фирм Franclin или keil, в состав которых входит язык программирования ASM-51. В этих программах создание строки вызова редактора связей производится автоматически при настройке программного проекта, а вызов редактора связей при помощи этой строки производится в ходе построения программного проекта. Настройка программного проекта происходит при подключении к нему новых программных модулей и при изменении его свойств, таких как разрешение или запрет создания карты памяти программы, выбор папки для хранения выходных файлов, разрешение или запрет помещения в выходной файл отладочной информации, разрешение или запрет создания загрузочного НЕХ-файла.

Использование сегментов в языке программирования ассемблер

При трансляции программы по частям возникает вопрос, как с этими частями работать. Иначе говоря, дает о себе знать проблема сегментов.

Справедливости ради необходимо отметить, что даже когда мы не задумываемся о сегментах, в программе присутствуют два сегмента: сегмент кода и сегмент данных. Если внимательно присмотреться к программе, то можно обнаружить, что кроме кодов команд в памяти программ хранятся константы, т. е. в памяти программ микроконтроллера располагаются, по крайней мере, два сегмента: код и данные. Чередование кода и данных может привести к нежелательным последствиям. Вследствие каких-либо причин данные могут быть случайно выполнены в качестве машинных команд или наоборот коды машинных команд могут быть восприняты и обработаны как данные.

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

1) кода;

2) переменных;

3) стека;

4) констант.

И лучше, если эти сегменты будут перемещаемыми. Тогда редактор связей сможет автоматически скомпоновать программу наилучшим способом.

Пример размещения сегментов в адресном пространстве памяти программ и внутренней памяти данных приведен на рис. 8.4. На этом рисунке видно, что при использовании нескольких сегментов переменных во внутренней памяти данных редактор связей может разместить меньший из них на месте неиспользованных банков регистров. Под сегмент стека обычно отводится вся область внутренней памяти, не занятая переменными. Это позволяет создавать программы с максимальным уровнем вложенности подпрограмм. Сегмент переменных, расположенный на рис. 8.4 во внешней памяти данных, при использовании современных микросхем, таких как AduC842, может находиться и в ОЗУ, расположенном на кристалле микроконтроллера.

Наиболее простой способ определения сегментов - это использование абсолютных сегментов памяти. При этом способе распределение памяти ведется вручную точно так же, как это делалось при использовании директивы EQU. В этом случае начальный адрес сегмента жестко задается программистом, и он же следит за тем, чтобы сегменты не перекрывались друг другом в памяти микроконтроллера. Использование абсолютных сегментов позволяет более гибко работать с памятью данных, т. к. теперь байтовые переменные в памяти данных могут быть назначены при помощи директивы резервирования памяти DS, а битовые переменные при помощи директивы резервирования битов DBIT.

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке