Предыдущий раздел РАЗДЕЛЬНАЯ ТРАНСЛЯЦИЯ ПРОГРАММЫ Следующая глава

17.5. Применение нескольких объектных модулей

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

Второе преимущество использования при получении программы нескольких объектных модулей – наиболее используемые из этих модулей могут быть получены один раз, а затем они могут быть включены в состав того или иного библиотечного файла. Это позволит использовать данные объектные модули многократно, в составе многих программ, получаемых многими программистами.

Третье преимущество многомодульной объектной структуры программы не используется в рассматриваемой простой ВС (DOS + i8086), но применяется очень широко в более сложных системах. Его сущность состоит в том,  что фрагменты машинной программы, каждый из которых получается в результате преобразования своего объектного модуля, могут быть загружены в различные разделы (сегменты) ОП так, что последующая работа программ с этими разделами будет производиться по отличным друг от друга правилам. Например, для некоторых разделов ОП допустима только операция “чтение”. В такие разделы целесообразно помещать неизменяемые данные программы, то есть ее константы. Для других разделов ОП система допускает только операцию “выполнение”. Сюда целесообразно помещать команды (“код”) машинной программы. Некоторые разделы ОП могут содержать данные (в том числе и “код”), одновременно используемые (разделяемые) несколькими программами. Подобное свойство широко используется в мультипрограммных ВС для реализации DLL – динамически связываемых библиотек.

Многомодульная объектная структура оказывает влияние на тексты исходных фрагментов. Причиной этого является наличие в тексте рассматриваемого исходного фрагмента внешних имен (см. п.17.2). При этом внешние выходные имена (метки) должны быть описаны с помощью псевдооператоров global. А внешние входные имена – с помощью псевдооператоров extern.

Например, переделаем последнюю exe-программу так, чтобы она была получена не из одного, а из двух исходных фрагментов. В первый исходный файл test1a.asm включим виртуальные сегменты кода и стека, а во второй test1b.asm – виртуальный сегмент данных. Текст первого исходного файла:

 

;             Программа выводит сообщение “Здравствуйте” на экран 

;             -------------------------------------------------------------------------

;                        

          segment      data                     ; Сегмент данных в другом файле

segment      stack                    ; Сегмент

times 64     db     0                 ;         стека

                   segment      code                    ; Сегмент кода

..start:

extern      Msg                       ; Сообщение в другом модуле

mov   ax, data                       ; Сделаем сегмент данных

          mov   ds, ax                          ;   адресуемым

mov   dx, Msg                       ;  DX ß адрес сообщения

mov   ah, 9                           ;  Вывод строки

int     21h                             ;    на экран

mov   ax, 4c00h                    ;  Возврат в DOS с

int     21h                             ;    кодом завершения 0

 

Текст второго файла:

 

;             Сегмент данных программы, которая выводит

;    сообщение “Здравствуйте” на экран 

;   -------------------------------------------------------------------------

;                        

cr                equ    0dh                                ;  Код ASCII возврата каретки

lf                 equ    0ah                                ;  Код ASCII перевода строки

segment      data                     ; Сегмент данных

global        Msg                      ; Используется в другом файле

Msg            db     ‘Здравствуйте’, cr, lf, ‘$’      ; Выводимое сообщение

 

Обратите внимание на то, что, несмотря на то, что виртуальный сегмент данных находится во втором файле, его заголовок “segment  data” присутствует и в первом (главном) файле. Кроме заголовка этот виртуальный сегмент может содержать и любые данные. В любом случае редактор связей соединяет в один логический сегмент одноименные виртуальные сегменты данных, кода или стека, объявленные в разных фрагментах исходной программы. Напомним, что фрагмент исходной программы состоит из одного или нескольких исходных файлов (исходных модулей), соединяемых в единое целое с помощью операторов %include.

Что касается имени виртуального сегмента, то оно может быть задано с помощью необязательного первого параметра оператора segment. Если этот параметр оператора segment опущен, то виртуальному сегменту присваивается имя, совпадающее с его типом. Например, в приведенном выше примере виртульные сегменты имеют имена: code, data и stack. Пример оператора, который присваивает виртуальному сегменту данных имя “data3”:

segment data3 data   

Н а б е р и т е и выполните приведенную выше программу.

 


Предыдущий раздел В начало Следующая глава