Читать «Assembler. Программирование на языке ассемблера IBM PC» онлайн - страница 160

Unknown Author

Пусть, к примеру, в программе имеются модули Ml и М2, состоящие из следующих сегментов (см. слева; для краткости для каждого сегмента указывается только его директива SEGMENT):

модуль Ml

модуль М2

программа M

класс

A SEGMENT ' DATA '

С SEGMENT 'DATA'

A

DATA

.. .

. . .

C

DATA

В SEGMENT

D SEGMENT 'CODE'

В

. ..

. . .

E

E SEGMENT

D

CODE

и пусть мы объединяем эти модули по приказу:

LINK Ml.OBJ+M2.OBJ,М.EXE;

Тогда в программе М сегменты будут расположены так, как указано справа.

Почему именно так? Сначала компоновщик просматривает первый из указанных ему модулей, т. е. Ml. Его сегменты, относящиеся к разным классам, не переупорядочиваются, а располагаются в том порядке, как они записаны в модуле: А В. Далее компоновщик просматривает сегменты модуля М2. Первый из них - сегмент С - имеет класс DATA. Компоновщик смотрит, был ли ранее сегмент того же класса. Да, был, это сегмент А, поэтому компоновщик размещает С вслед за А, "отодвигая” В: А С В. Следующий сегмент D имеет класс CODE, но среди предыдущих сегментов не было сегмента такого класса, поэтому компоновщик размещает D в конце последовательности: А С В D. Последний сегмент Е относится к классу с "пустым" именем, а так как до этого уже был сегмент В того же класса, то компоновщик располагает его вслед за В и перед D. Поскольку других сегментов и модулей нет, то данное расположение сегментов является окончательным.

12.3.2. Параметр Объединение**

Этот параметр может принимать следующие значения: PUBLIC, STACK, AT и COMMON.

Значение PUBLIC

Как уже сказано, сегменты одного класса всегда располагаются в памяти рядом. Однако каждый из них сохраняет свою независимость. Это означает, что прежде чем обратиться к любому из этих сегментов, надо установить соответствующий сегментный регистр на начало данного сегмента. А это лишние команды, лишний расход времени. Этого можно избежать, если объединить сегменты в единый сегмент. Например, можно считать, что в нашей программе имелся только один сегмент данных, но по каким-то причинам мы описали его по частям в разных модулях, и вот теперь, при компоновке программы из модулей, мы собрали эти части вместе и получили единый исходный сегмент данных. Теперь достаточно один раз установить соответствующий сегментный регистр на начало единого сегмента и далее, не меняя значение регистра, осуществлять по нему доступ ко всем ячейкам сегмента.

Такое объединение сегментов происходит, если в качестве параметра "объединение" в директивах SEGMENT, начинающих эти сегменты, указано слово PUBLIC. Более точно правило объединения следующее: компоновщик объединяет в один сегмент такие сегменты (из любых модулей), у которых одно и то же имя, которые относятся к одному и тому же классу и в директивах SEGMENT которых указан тип объединения PUBLIC. Если хотя бы одно из этих трех условий нарушено (у сегментов разные имена, разные классы или разные типы объединения), тогда сегменты не объединяются. В частности, сегмент, для которого не указан параметр "объединение", не будет объединяться ни с каким другим сегментом.