С помощью AT-сегментов обычно вводятся ассемблерные обозначения для фиксированных участков памяти (вектор прерываний, видеопамять). Чтобы не менять их содержимое, в состав AT-сегментов не должны входить предложения, порождающие машинный код, т.е. запрещены любые команды, директивы DB, DW, DD с операндами, отличными от ?, и т.п. Если подобные предложения все-таки имеются, тогда компоновщик блокирует запись в память их машинного кода.
- Значение COMMON
Все сегменты, которые имеют одно и то же имя, относятся к одному и тому же классу и в директиве SEGMENT которых указан параметр COMMON, компоновщик располагает в памяти с одного и того же адреса (с адреса, по которому размещен первый из этих сегментов), накладывая их содержимое друг на друга.
Когда отдельно ассемблированные программы должны объединяться компоновщиком, то можно использовать типы: PUBLIC, COMMON и STACK. В случае, если программа не должна объединяться с другими программами, то данная опция может быть опущена.
3. Класс. Данный элемент, заключенный в апострофы, используется для группирования относительных сегментов при компоновке:
<имя> SEGMENT PARA STACK 'Stack'
В этом параметре в апострофах указывается некоторое имя которое рассматривается как имя класса, к которому относится сегмент. Дело в том, что в многомодульной программе компоновщик LINK располагает сегменты в следующем порядке: сначала сегменты из первого модуля, затем из второго, и т.д. Но иногда желательно разместить родственные сегменты из разных модулей рядом. И тогда, если какие-то сегменты отнесены к одному классу, компоновщик расположит их рядом. Надо отметить, что все сегменты, для которых не указан класс, считаются относящимися к одному и тому же классу с "пустым" именем.
После директивы SEGMENT необходимо указать директиву ASSUME, определяющую соответствие между сегментным регистром и именем сегмента. Директива ASSUME имеет вид:
ASSUME <имя_сегментного_регистра>:<имя_сегмента>.
Например, ASSUME SS:< имя_стека>. Эта директива указывает, что транслятор должен связывать имя сегмента стека с именем сегментного регистра SS. Можно использовать одну директиву ASSUME для нескольких сегментов, например, директива:
ASSUME SS:<имя_сегм_стека>, DS:<имя_сегм_данных>, CS:<имя_сегм_кода> указывает, что ассемблер должен ассоциировать имя сегмента стека с регистром SS, имя сегмента данных – с именем регистра DS, а имя сегмента кода – с именем регистра CS. Параметры в директиве ASSUME могут записываться в любой последовательности. Регистр ES также может присутствовать в числе операндов. Если программа не использует регистр ES, то его можно опустить или указать ES:NOTHING. Нужно отметить, что директива ASSUME не загружает в сегментные регистры начальные адреса сегментов. Этой директивой автор программы лишь обещает, что в программе будет сделана такая загрузка. Директива ASSUME можно размещать в любом месте программы, но обычно ее размещают в начале сегмента команд. Каждая новая директива ASSUME для какого-то регистра отменяет все предыдущие определения.
Начальная загрузка сегментных регистровтребуется, т.к. нужно, чтобы в сегментных регистрах находились правильные значения – номера соответствующих сегментов памяти. Но в начале выполнения программы в этих регистрах ничего нет. Поэтому выполнение надо начать с команд, которые загружают в сегментные регистры номера соответствующих сегментов памяти. Рассмотрим пример: пусть регистр DS надо установить на начало сегмента B. Однако, сделать это командой MOV DS, B нельзя. Поэтому пересылку надо делать через другой, несегментный регистр, например, AX: