Читать «Assembler. Программирование на языке ассемблера IBM PC» онлайн - страница 161
Unknown Author
Пример:
A SEGMENT PUBLIC 'Q'
В SEGMENT
С SEGMENT
A SEGMENT
ртУвыс
PUBLIC
'Q' A SEGMENT 'Q'
'Q'
А(М1)
А (М2)
С
А(МЗ)
В
В окончательной программе сегменты А из модулей Ml и М2 объединены в один сегмент, а сегменты С из М2 и А из М3 располагаются рядом с этим общим сегментом, т. к. имеют тот же класс Q, но не объединяются с ним, поскольку у С иное имя, а у А из М3 не указан параметр PUBLIC. Отметим, что если бы сегмент А из модуля М2 не объединялся с сегментом А из модуля Ml, то он располагался бы вслед за сегментом С, но объединяемые сегменты, конечно, размещаются рядом, ”отодвигая" остальные сегменты.
Теперь уточним, в чем разница между объединением сегментов и просто расположением сегментов рядом в памяти. Пусть имеются два модуля:
;модуль Ml
ofs
;модуль М2
EXTRN Z:WORD
PUBLIC Z
A SEGMENT PUBLIC 'Q'
A SEGMENT PUBLIC
X DW ?
0
Z DW ?
Y DB ?
2
A ENDS
A ENDS
. ..
ofs
и пусть регистр ES установлен на начато сегмента А из Ml. Рассмотрим, как будет транслироваться и выполняться команда MOV BX,ES:Z из модуля Ml.
Если бы оба сегмента А не были объединены (например, у одного из них не было бы параметра PUBLIC), тогда смещения имен в каждом из них отсчитывались бы от начала сегмента (см. колонки ofs). Поэтому имя Z в нашей команде было бы заменено на смещение 0:
MOV BX,ES:Z ==> MOV BX,ES:0
Поскольку, согласно нашему предположению, регистр ES указывает на сегмент А из модуля Ml, то эта команда проработает неправильно: в регистр ВХ будет записано значение переменной X, а не переменной Z. Для правильного доступа к переменной Z надо перед нашей командой установить регистр ES на начало сегмента А из модуля М2, а это лишние команды. И здесь не играет никакой роли, рядом ли в памяти расположены сегменты или нет.
Если же оба сегмента А объединены, тогда сегмент А из модуля М2 считается продолжением сегмента А из модуля Ml:
A SEGMENT ; ofs
X DW ? ; 0
Y DB ? , ; 2
; (пропуск 13 байтов)
Z DW ? ; lOh
A ENDS
Это означает, что теперь смещения всех имен этого объединенного сегмента будут отсчитываться от начала данного сегмента и именно на эти смещения будут заменяться имена (таким пересчетом и коррекцией команд занимается компоновщик). Например, имя Z теперь будет заменяться не на смещение 0, а на смещение 10h. Почему на 10h (=16), а не на 3? Здесь надо вспомнить, что сегменты располагаются в памяти с адресов, кратных 16, и это правило действует, даже если сегменты объединяются. Поэтому сегмент А из М2 подсоединяется к сегменту А из Ml, но не впритык, а с ближайшего адреса, кратного 16, и тем самым между переменными Y и Z будет оставлено свободными 13 байтов (от этого зазора можно и избавиться - см. разд. 12.3.3). Итак, смещение имени Z равно 10h, поэтому в нашей команде имя Z будет заменено на 10h: