АССЕМБЛЕР. Компоновщик. Загрузчик. Макрогенератор


По этой директиве ассемблер заполняет


По этой директиве ассемблер заполняет ТРСР, создавая пары DS и S2, CS и S3, SS и S1. Поскольку эта директива носит чисто информационный характер, то СР не меняется.

Директива ENDS:  S2 ENDS

Ассемблер фиксирует, что сегмент S2 закрыт, и в ТС заносит размер этого сегмента, т.е. число байтов, занятых всеми предложениями сегмента. Этот размер определяется очень просто - он равен текущему значению СР. Таким образом, СР используется не только для определения соответствия между именами и адресами, но и для подсчета размеров сегментов.

            Обработка команды, например: ADD X,K

На 1-м проходе ассемблер не формирует машинные команды, поэтому сейчас ему безразлично, на какой цифровой КОП надо заменять мнемокод ADD, на какой адрес заменять имя X и т.д. Единственное, что ему сейчас важно знать, - это сколько байтов в памяти займет соответствующая машинная команда, на сколько надо увеличить СР. Это число определяется так.

Размер команды зависит (помимо мнемокода) от двух вещей: от типов операндов и от того, надо или нет перед этой командой ставить префикс сегментного регистра. (Тип операндов - байты это или слова - не влияет на размер команды, просто КОПы будут отличаться одним из битов.)

Типы операндов определяются по ТИ. Ассемблер выделяет из команды первый операнд (имя X), лезет в ТИ и узнает, что это имя переменной размером в слово, т.е. этот операнд имеет тип m16. Затем ассемблер выделяет второй операнд (имя K) и по ТИ узнает, что это имя константы со значением 3; это значение может быть байтом или словом, но поскольку тип 1-го операнда команды равен word, то и этой константе приписывается тип word, т.е. i16. (В общем случае операнды задаются более сложными выражениями, скажем BYTE PTR X

или K/2+1, и их типы устанавливаются сложнее, однако, зная по ТИ типы простейших элементов этих выражений, можно установить и тип выражения в целом.) Узнав типы операндов, ассемблер лезет в таблицу мнемокодов и отыскивает в ней строку с нужным мнемокодом и нужными типами операндов, а из этой строки узнает размер соответствующей машинной команды. В нашем случае в строке для мнемокода ADD и типов m16 и i16 сказано, что размер команды равен 6.



Однако это еще не окончательный размер команды, надо еще определить, должен ли в этой команде использоваться префикс или нет. Если бы этот префикс был указан в команде явно (типа DS:X), тогда здесь проблемы не было бы. Но, как правило, в программах на ЯА такой префикс опускается с расчетом, что, если надо, его подставит сам ассемблер. Для этого ассемблер по ТИ узнает, в каком сегменте описано имя X

(пусть это сегмент S2), а по ТРСР узнает, какой сегментный регистр поставлен в соответствие этому сегменту (пусть это регистр DS). Тем самым ассемблер устанавливает, что X - это на самом деле сокращение адресной пары DS:X. После этого ассемблер смотрит, не совпадает ли сегментный регистр из этой пары с тем сегментным регистром, который подразумевается в данной команде по умолчанию. Как известно, в команде ADD по умолчанию подразумевается регистр DS. Это значит, что перед нашей машинной командой можно не ставить префикс DS:. Тем самым по данной символьной команде в памяти будет занято 6 байтов, поэтому ассемблер увеличивает СР на 6 и за этом заканчивает обработку данной команды.

Но если бы имя X было описано в сегменте, на начало которого (согласно ТРСР) установлен иной регистр, скажем ES, который не совпадает с префиксом, подразумеваемым по умолчанию, тогда опускать префикс ES: перед машинной командой уже нельзя, поэтому всего символьная команда займет 6+1=7 байтов (префиксы DS:, ES: и т.п. - это самостоятельные однобайтовые машинные команды) и поэтому ассемблер увеличит СР на 7.

Директива  END

По этой директиве ассемблер узнает, что текст программы закончился, поэтому он завершает свой 1-й проход. Цель этого прохода - построение ТИ и ТС - достигнута.


Содержание раздела