Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ВС сети и телекомм-практикум.doc
Скачиваний:
45
Добавлен:
01.07.2025
Размер:
613.89 Кб
Скачать

7. Сегменты

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

Для того, чтобы начать работу с сегментом, используется директива SEGMENT, а для завершения работы с сегментом – директива ENDS. Рассмотрим формат подобного действия:

имя сегмента SEGMENT выравнивание тип разряд 'класс'

...

имя сегмента ENDS

Как мы видим, директива SEGMENT имеет пять операндов. Однако, ни один из них не является обязательным. Если мы не указываем в тексте программы какие-либо из них, то они будут установлены по умолчанию. Разберем назначение этих операндов и возможные их вариации.

Имя сегмента – обычная метка, используемая для получения адреса сегмента. Также помогает при комбинировании сегментов в группы. Имя должно быть уникально. Существуют установившиеся традиции использовать имя cseg для сегмента кода, dseg для сегмента данных и sseg для сегмента стека.

Выравнивание – указывает ассемблеру на границу памяти, с которой должен начинаться сегмент. Может иметь значения:

- BYTE – с любого адреса;

- WORD – с четного адреса;

- DWORD – с адреса, кратного 4;

- PARA – с адреса, кратного 16 (граница параграфа);

- PAGE – с адреса, кратного 256.

Необходимо учитывать, что при отсутствии указанного значения выравнивание будет происходить по границе параграфа.

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

- PUBLIC. Все такие сегменты с одинаковым именем, но разными классами объединяются в один;

- STACK. Аналогичен типу PUBLIC, но рекомендуется использовать лишь для сегментов стека. Дело в том, что сегмент, полученный объединением всех сегментов типа STACK, будет использоваться как стек;

- COMMON. Сегменты с одинаковым именем, как и в варианте с PUBLIC, объединяться в один, но с одним нюансом. Объединение не последовательное, а то одному и тому же адресу. Это значит, что общий объем равен не сумме объемов сегментов, а объему наибольшего из объединяемых. Следовательно, при таком объединении высоковероятная потеря нужной информации. Однако, подобным образом удобно строить оверлейные программы;

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

- PRIVATE. Сегмент такого типа не объединяется с другими сегментами.

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

Разрядность. Бывает USE16 и USE32. В первом случае сегмент не превышает 64 Кб, и все команды и адреса в этом сегменте считаются 16-битными. Нет, там можно применять ориентированные на 32 разряда команды, но происходит это с меньшей эффективностью, требуя больше ресурсов и машинного времени.

Во втором случае размер сегмента практически неограничен. Конечно в теории он не может быть больше 4 Гб, но вряд ли кому-либо придет в голову создавать сегмент подобного размера. Все команды и адреса по умолчанию 32-битные.

Класс сегмента – это любая метка, взятая в одинарные кавычки. Все сегменты с одинаковым классом, даже сегменты типа PRIVATE, будут расположены в исполняемом файле непосредственно друг за другом.

Если в программе определено много сегментов, мы можем объединить их в группу следующим образом:

имя группы GROUP имя сегмента

Второй операнд – список имен сегментов, которые объединяются в группу. Имя группы теперь можно применять вместо имен сегментов для получения сегментного адреса и для директивы ASSUME.

ASSUME регистр:связь

ASSUME устанавливает связь между сегментом (группой сегментов) и сегментным регистром, делая это следующим образом:

ASSUME регистр:связь

ASSUME cs:cseg, ds:dseg, ss:sseg

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

Директива ENDS завершает сегмент. Ее единственный операнд, имя сегмента, ставится перед ней.

В конце же программы ставится директива END, а после нее в строке указывается метка, с которой программа начиналась. Например:

start:

END start

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

Для того, чтобы писать простейшие программы, данного материала достаточно, за исключением работы с прерываниями. Ее мы далее и рассмотрим.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]