Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Микропроцессорные системы (книга Комаров) / Модульное программирование.doc
Скачиваний:
82
Добавлен:
08.03.2015
Размер:
276.99 Кб
Скачать

Объединение логических сегментов

Предположим, что разрабатываемая программа состоит из двух файловых модулей MOD1.asm и MOD2.asm, каждый из которых содержит сегменты программного кода, данных и стека. Пусть эти сегменты соответственно имеют имена Code1, Data1, Stack1 и Code2, Data2, Stack2 и определены конструкцией:

Имя_сегмента SEGMENT

. . . . . .

Имя_сегмента ENDS

При объединении таких модулей редактором связей (LINK MOD1+MOD2) размещение программы в памяти будет иметь вид, приведенный на рис.5.1,а. При этом соответствующие логические сегменты обоих модулей не могут адресоваться при неизменном содержимом сегментных регистров. Поэтому при каждой передаче управления между модулями необходимо изменять регистр CS, а при обращении к данным из различных модулей модифицировать регистр DS. Самым неприятным является то, что программа должна иметь один стек, и, следовательно, один из сегментов стека оказывается ненужным, а размер другого может оказаться недостаточным для работы полной программы.

Рис. 5.1. Обобщенная схема объединения логических сегментов:

а) без описания типа объединения;

б) с описанием типа объединения

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

Возможны различные типы объединения логических сегментов. Описание типа объединения приводится в директиве SEGMENT. Полный формат конструкции описания логического сегмента имеет вид:

Имя_сегмента SEGMENT{Тип_выравнивания}{Тип_объединения}{'Имя_класса'}

. . . . . . . . .

. . . . . . . . .

Имя_сегмента ENDS

Параметр "Тип_выравнивания" определяет адресную границу, начиная с которой логический сегмент будет размещаться в памяти. Этот формальный параметр может принимать следующие основные фактические значения: PARA,WORDиBYTE.

Атрибут PARAуказывает, что объединяемые логические сегменты должны начинаться с границы параграфа, то есть с адреса, кратного 16. Поскольку размер параграфа равен 16 байтам, то в этом случае между сегментами может оказаться от 0 до 15 неиспользуемых байтов, что соответствует потерям памяти до 15 байтов для каждой границы между сегментами. АтрибутPARAможет использоваться для любых логических сегментов и принят по умолчанию.

Атрибут WORDобеспечивает начало сегментов с четного адреса. Поскольку обращение к словам по четным адресам осуществляется быстрее, чем к словам по нечетным адресам, то этот атрибут наиболее целесообразно использовать для сегмента стека. Потери памяти в этом случае могут составлять до 1 байта для каждой границы между объединяемыми сегментами.

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

Параметр "Тип_объединения" определяет способ объединения одноименных логических сегментов связываемых файловых модулей. Сегменты с различными именами не объединяются, а при наличии одноименных сегментов без описания типа объединения редактор связей зафиксирует ошибку. Это обусловлено тем, что сегмент без описания типа объединения рассматривается как независимая программная часть и не может объединяться ни с чем. Формальный параметр "Тип_объединения" может принимать следующие основные фактические значения: PUBLIC,STACK,COMMONиAT.

Атрибут PUBLICобеспечивает объединение одноименных логических сегментов путем их конкатенации (сцепления). Порядок сцепления определяется последовательностью имен объектных файлов в команде вызова LINK. При этом смещения переменных или меток в первом из связываемых модулей остаются неизменными, а во всех последующих модулях корректируются с учетом суммарного размера ранее объединенных сегментов.

Пример 5.2:

Объединить в общую программу модулиMOD1 и MOD2.

Пусть в исходных модулях описаны сегменты данных вида:

; В модуле MOD1.asm

PrData SEGMENT WORDPUBLIC

Dig DB10h,11h,12h,13h

PrData ENDS

; В модуле MOD2.asm

PrData SEGMENT WORDPUBLIC

BV1 DB21h

BV2 DB?

BV3 DB23h

PrData ENDS

и редактор связей вызывается командной строкой LINK MOD1+MOD2,PROG;.

Тогда схема распределения памяти, соответствующая объединению этих модулей будет иметь вид, приведенный на рис.5.2,а. Редактор связей скорректировал адреса переменных из логического сегмента PrData модуля MOD2 на значение, равное объему одноименного сегмента модуля MOD1. При этом общий размер объединенного сегмента PrData равен сумме размеров объединяемых сегментов.

Атрибут PUBLIC используется для объединения сегментов программного кода и сегментов данных.

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

Рис. 5.2. Объединение логических сегментов:

а) по типу PUBLIC; б) по типу STACK; в) по типу COMMON

Пример 5.3:

Объединить в общую программу модули MOD1 и MOD2.

Пусть в исходных модулях описаны сегменты стека вида:

; В модуле MOD1.asm

PrStack SEGMENT WORDSTACK

DW2DUP (1111h)

StkTop LABEL WORD

PrStack ENDS

; В модуле MOD2.asm

PrStack SEGMENT WORDSTACK

DW 2222h

TopStk LABEL WORD

PrStack ENDS

и редактор связей вызывается командой LINK MOD1+MOD2,PROG;.

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

Смещения в командах LEA SP,StkTop и LEA SP,TopStk , загружающих верхушки пустых стеков в исходных модулях, автоматически корректируются так, что в SP загружается верхушка Top объединенного пустого стека.

Атрибут COMMON обеспечивает объединение одноименных логических сегментов путем их наложения друг на друга так, чтобы они имели один и тот же начальный адрес. Размер общего сегмента равен размеру максимального из объединяемых сегментов. Если данные инициализированы более, чем в одном сегменте, то данные, объявленные последними, замещают все предыдущие.

Пример 5.4:

Объединить в общую программу модули MOD1 и MOD2.

Пусть в исходных модулях описаны сегменты данных вида:

; В модуле MOD1.asm

PrData SEGMENT WORDCOMMON

Dig DB10h,11h,12h,13h

PrData ENDS

; В модуле MOD2.asm

PrData SEGMENT WORDCOMMON

BV1 DB21h

BV2 DB?

BV3 DB23h

PrData ENDS

и редактор связей вызывается командной строкой LINK MOD1+MOD2,PROG; .

Схема распределения памяти, соответствующая объединению этих модулей, будет иметь вид, приведенный на рис.5.2,в.

Атрибут COMMONиспользуется для объединения сегментов данных при организации оверлейных программ. При этом переменные и метки из одноименных сегментов всех файловых модулей будут иметь одинаковые адреса.

Во всех вышерассмотренных случаях описания сегментов они являются перемещаемыми, и их начальный адрес определяется загрузчиком операционной системы во время загрузки исполняемого файла программы в память. Однако, часто требуется разместить сегмент по фиксированному адресу. Это необходимо, например, для обращения к фиксированным областям памяти (таблице векторов прерываний, буферу экрана, ПЗУ или ОЗУ в МПС).

Для задания абсолютного адреса сегмента служит тип объединения AT, записываемый в формате:

ATЧисловое_выражение

Значение числового выражения определяет начальный адрес логического сегмента, что обеспечивает его фиксацию в адресном пространстве. Числовое выражение может быть представлено любой корректной константой без ссылок вперед.

Как правило, тип объединения AT используется для сегментов данных или стека. Такой сегмент содержит описание переменных, имена которых используются в сегменте программного кода для обращения к соответствующим ячейкам памяти.

Особенностью директивы AT является то, что редактор связей LINK не помещает в соответствующий ей сегмент инициализированные данные или программный код. Поэтому идентификаторы сегментаATиспользуются только для обращения к ячейкам памяти, а их инициализация должна осуществляться каким-либо другим, например, программным путем. Это особенно характерно для МПС, не имеющих операционной системы и требующих программной инициализации всех необходимых ячеек памяти данных.

Для задания абсолютного смещения offset внутри сегмента служит директива ORG, записываемая в формате:

ORGЧисловое_выражение

Значение числового выражения определяет абсолютное смещение относительно начала сегмента, в котором находится эта директива.

Пример 5.5:

Обеспечить обращение к фиксированному сегменту по адресуB800hи к фиксированным ячейкам памяти в нем:

Data SEGMENTAT0B800h;Описание фиксированного сегмента

V1 DW5555h ;Эти переменные не будут инициали-

V2 DW3333h ;зированы и примут нулевые значения

ORG 10h ;Задание фиксированного смещения

;offset=16

V3 DB? ;Описание переменных

V4 DW ?

Data ENDS

Code SEGMENT

ASSUME CS:Code, DS:Data

Start:

MOV AX, Data ;Инициализация DS

NOV DS, AX

MOV AX, V1 ;Эти регистры будут загружены

MOV DX, V2 ;нулевым значением

MOV V1, 5555h ;Программная инициализация

MOV V2, 3333h ;переменных

MOV V3, 22h

MOV V4, 4444h

Code ENDS

ENDStart

Параметр "Имя_класса" определяет порядок следования логических сегментов в памяти. Сегменты одного класса размещаются в памяти один за другим. После их размещения аналогичным образом размещаются сегменты других классов. Все сегменты имеют класс. Сегменты, для которых класс не указан, считаются принадлежащими к классу с пустым именем. Количество сегментов одного класса неограничено, но их суммарный объем не должен превышать 64 килобайта. Для характеристики класса сегмента может использоваться любой идентификатор.

Пример 5.6:

Обеспечить размещение сегментов программного кода и констант, а также данных и стека в смежных областях памяти.

Для этого перечисленные сегменты должны описываться следующим образом:

Code SEGMENT BYTEPUBLIC'ROM'

. . . . . . . . . . . . . . . .

Code ENDS

Data SEGMENT WORD PUBLIC'RAM'

. . . . . . . . . . . . . . . .

Data ENDS

Stack SEGMENT WORDSTACK'RAM'

. . . . . . . . . . . . . . . .

Stack ENDS

Const SEGMENT BYTE PUBLIC'ROM'

. . . . . . . . . . . . . . . .

Const ENDS

При этом сегменты Code и Const будут размещены в области памяти с именем ROM, а сегменты Data и Stack в области с именем RAM.

Другим способом управления последовательностью сегментов является использование ключа /A в командной строке вызова ассемблера MASM. В этом случае MASM размещает сегменты в объектном файле в алфавитном порядке.

Соседние файлы в папке Микропроцессорные системы (книга Комаров)