ДИРЕКТИВЫ СЕГМЕНТАЦИИ

Программа состоит из описаний сегментов.

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

Сегменты могут описываться в любой последовательности, и количество сегментов данных и кодов команд не ограничивается. В одном из сегментов кодов программы обычно присутствует метка, являющаяся точкой входа в программу. Эта метка указывается в последней директиве END, заставляющей транслятор завершить свою работу.

Вне сегментов указываются директивы транслятора, определяющие общие особенности трансляции программы.

Описание сегмента начинается с директивы SEGMENT и оканчивается директивой ENDS, перед которыми указывается имя сегмента. После ключевого слова SEGMENT могут следовать аргументы, описывающие атрибуты сегмента.

Атрибут выравнивания (тип выравнивания) сообщает компоновщику о том, что нужно обеспечить размещение сегмента на заданной границе. По умолчанию тип выравнивания имеет значение PARA. Допустимые значения этого атрибута следующие:

♦ BYTE – выравнивание не выполняется. Сегмент может начинаться с любого адреса оперативной памяти;

♦ WORD – сегмент начинается по адресу, кратному двум (выравнивание на границу слова);

♦ DWORD – выравнивание на границу двойного слова;

♦ PARA – выравнивание на границу параграфа, то есть по адресу, кратному 16;

♦ PAGE – выравнивание на границу страницы размером 256 байт;

♦ MEMPAGE – выравнивание на границу страницы размером 4 Кбайт.

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

♦ PRIVATE – сегмент не будет объединён с другими сегментами с тем же именем вне данного модуля.

♦ PUBLIC – заставляет компоновщик соединить все сегменты с одинаковыми именами. Новый объединенный сегмент будет целым и непрерывным. Все адреса (смещения) будут вычисляться относительно начала этого нового сегмента.

♦ COMMON – располагает все сегменты с одним именем по одному адресу. Все сегменты с данным именем будут перекрываться и совместно использовать оперативную память. Размер сегмента будет равен размеру самого большого сегмента.

♦ AT xxxx – располагает сегменты по абсолютному адресу параграфа (кратный 16), который задаётся выражением хххх. Компоновщик располагает сегмент по заданному адресу (это можно использовать для доступа к видеопамяти или области ПЗУ), учитывая атрибут комбинирования.

♦ STACK – определение сегмента стека. Заставляет компоновщик соединить все одноименные сегменты и вычислять адреса в этих сегментах относительно регистра SS. Если сегмент стека создан, а комбинированный тип STACK не использован, программист должен явно загрузить в регистр SS адрес сегмента (как это делается для регистра DS).

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

Атрибут размера сегмента. Для микропроцессора i80386 и выше сегментные регистры могут быть 16- или 32- разрядными. Это влияет, прежде всего, на размер сегмента и порядок формирования физического адреса внутри него. Атрибут может принимать следующие значения:

♦ USE16 – это означает, что сегмент допускает 16-разрядную адресацию. При формировании физического адреса может использоваться только 16-разрядное смещение. Соответственно, такой сегмент может содержать до 64 Кбайт кода или данных;

♦ USE32 – сегмент будет 32-разрядный. При формировании физического адреса может использоваться 32-разрядное смещение. Поэтому такой сегмент может содержать до 4Гбайт кода или данных.

Все сегменты сами по себе равноправны, так как директивы SEGMENT и ENDS не содержат информации о функциональном назначении сегментов. Для того, чтобы использовать их как сегменты кода, данных или стека необходимо предварительно сообщить транслятору об этом, для чего используют специальную директиву ASSUME. Эта директива сообщает транслятору о том, какой сегмент к какому сегментному регистру привязан.