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

Unknown Author

Итак, поместив директиву EXTRN в модуль М2, мы сообщили ассемблеру, что имена X и К являются внешними, т. е. описанными в другом модуле (в каком именно - указывать не надо). Однако этого мало. Надо также в том модуле, где эти имена описаны (т. е. в Ml), поместить директиву PUBLIC, перечислив в ней эти имена:

PUBLIC <имя>,    <имя>

Эта директива может указываться любое число раз и в любых местах модуля.

В нашем конкретном случае в модуле Ml надо записать директиву

public х,к

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

Отметим, что имена, перечисленные в директиве PUBLIC, обязательно должны быть описаны в модуле и что в директиве их типы указывать не надо.

Может возникнуть вопрос: а зачем в модуле Ml указывать, что имена X и К являются общими? Разве недостаточно директивы EXTRN в модуле М2? Оказывается, недостаточно. Дело здесь в следующем. Модули Ml и М2 транслируются по отдельности и объединяются лишь после того, как будут переведены на машинный язык. Но в машинном варианте модуля Ml не останется никаких имен, поэтому, когда при объединении модулей программы в модуле М2 надо будет заменять имена X и К на соответствующие адрес и число, сделать это уже не удастся - в модуле Ml нужной информации не будет. Так вот, чтобы при трансляции модуля Ml ассемблер сохранил нужную информацию об именах X и К, мы и указываем директивой PUBLIC на особую роль этих имен. Встретив эту директиву, ассемблер сохранит в объектном модуле Ml необходимую информацию об именах X и К, которой затем, при объединении модулей, и воспользуется компоновщик.

Итак, если в каком-то модуле программы некоторое имя описано как внешнее, то в каком-то другом модуле это имя обязательно должно быть объявлено общим. При этом никакое имя не должно быть объявлено общим в нескольких модулях программы, иначе будет путаница.

С учетом всего сказанного наши модули Ml и М2 должны иметь следующий вид:

; модуль Ml EXTR1T P:FAR PUBLIC Х,К

; модуль М2

EXTRN X:BYTE,K:ABS PUBLIC Р

X DB ?    Р PROC FAR

К EQU 100

MOV X,0

CALL P    MOV AX,К

12.23. Сегментирование внешних имен

Следующая проблема, которая возникает в многомодульных программах, - это проблема сегментирования внешних имен.

Обратите внимание, что в директиве EXTRN не указывается, по какому сегментному регистру надо сегментировать внешнее имя. А это важно знать ассемблеру, т. к. от этого зависит, как он должен транслировать команду, содержащую такое имя. Например, если имя X надо сегментировать по регистру ES, тогда команда MOV Х,0 должна восприниматься как MOV ES:X,0, т. е. ассемблер должен добавлять префикс ES:. Но если имя X должно сегментироваться по регистру DS, тогда префикс DS:, который подразумевается в команде MOV по умолчанию, ассемблер не должен подставлять. Конечно, если перед внешним именем явно указан префикс (например, MOV ES:X,0), тогда проблем нет, но обычно имена указываются без префиксов, поэтому и возникает проблема с выбором по умолчанию сегментных регистров для внешних имен. В ЯА эта проблема решается следующим образом: