Директива ASSUME

Директива EQU

 

Константы в языке Ассемблера описываются с помощью директивы эквивалентности EQU, имеющей следующий синтаксис:

<имя> EQU <операнд>

 

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

 

 

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

 

ASSUME <пара>[[, <пара>]]

ASSUME NOTHING

 

где <пара> - это <сегментный регистр> :<имя сегмента>

либо <сегментный регистр> :NOTHING

 

Например, директива

 

ASSUME ES:A, DS:B, CS:C

 

сообщает ассемблеру, что для сегментирования адресов из сегмента А выбирается регистр ES, для адресов из сегмента В – регистр DS, а для адресов из сегмента С – регистр CS.

Таким образом, директива ASSUME дает право не ука­зывать в командах (по крайней мере, в большинстве из них) префиксы – опущенные префиксы будет самостоятельно восстанавливать ассемблер.

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

Если в директиве ASSUME указано несколько пар с одним и тем же сегментным регистром, то последняя из них «отменяет» предыдущие, т. к. каждому сегментному регистру, можно поставить в соответствие только один сегмент. В то же время на один и тот же сегмент могут указывать разные сегментные регистры. Если в директиве ASSUME в качестве второго элемента пары задано служебное слово NOTHING (ничего), например, ASSUME ES: NOTHING, то это означает, что с данного момента сегментный регистр не указывает ни на какой сегмент, что ассемблер не должен использовать этот регистр при трансляции команд.

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

Загрузка производится следующим образом. Пусть регистр DS необходимо установить на начало сегмента В. Для загрузки регистра необходимо выполнить присваивание вида DS:=B. Однако сделать это командой MOV DS,B нельзя, поскольку имя сегмента – это константное выражение, т. е. непосредственный операнд, а по команде MOV запрещена пересылка непосредственного операнда в сегментный регистр (см. ниже). Поэтому такую пересылку следует делать через другой, несегментный регистр, например, через АХ:

 

MOV АХ,В

MOV DS,AX ;DS:=B

 

Аналогичным образом загружается и регистр ES.

Регистра CS загружать нет необходимости, так как к началу выполнения программы этот регистр уже будет указывать, на начало сегмента кода. Такую загрузку выполняет операционная система, прежде чем передает управ­ление программе.

Загрузить регистр SS можно двояко. Во-первых, его можно загрузить в самой программе так же, как DS или ES. Во-вторых, такую загрузку можно поручить операционной системе. Для этого в директиве SEGMENT, открывающей описание сегмента стека, надо указать специальный параметр STACK, например:

 

S SEGMENT STACK

...

S ENDS

 

В таком случае загрузка S в регистр SS будет выполнена автоматически до начала выполнения программы.