Иллюстрированный самоучитель по теории операционных систем

Относительная загрузка

Довольно легко построить и пример кода, в котором адресация происходит вообще без явного использования каких-либо регистров, во всяком случае, без загрузки в них значений (пример 3.4).

Пример 3.4. Реализация косвенного перехода по адресу dst_seg:dst_offs:

push dst seg
; Это и будет ссылкой на абсолютный адрес
push dst_offs
retf

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

Ассемблер при каждой ссылке на такой символ генерирует не только "заготовку" адреса в коде, но и запись в таблице перемещений (relocation table). Эта запись хранит место ссылки на такой символ в коде или данных. Если в ссылке используется только часть адреса, как в командах sethi %10, %hi(addr) процессора SPARC, или move ax, segment addr Процессора 8086, мы запоминаем и этот факт.

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

Файл, содержащий таблицу перемещений, гораздо сложнее абсолютного загружаемого модуля и носит название относительного или перемещаемого загрузочного модуля. Именно такой формат имеют ехе-файлы в системе MS DOS (пример 3.5).

Пример 3.5. Заголовок ЕХЕ-файла MS DOS. Цитируется по WINT.H из поставки 1; MS Visual C++ v6.0 (перевод комментариев автора):

#define IMAGE_DOS_SIGNATURE Ox4D5A // MZ
typedef struct _IMAGE_DOS_HEADER { // Заголовок DOS.EXE
WORD e_magic; // Магическое число (сигнатура)
WORD e_cblp; // Длина последней страницы файла в байтах
WORD e_cp; // Количество страниц в файле
WORD e_crlc; // Количество перемещений
WORD e_cparhdr; // Размер заголовка в параграфах
WORD ejrainalloc; // Минимальное количество дополнительных параграфов
ORD e_maxalloc; // Максимальное количество дополнительных параграфов
WORD e ss; // Начальное (относительное) значение SS
WORD e_sp; // Начальное значение SP
WORD e_csum; // Контрольная сумма
WORD e_ip; // Начальное значение IP
WORD e_cs; // Начальное (относительное) значение CS
WORD e_lfarlc;// Адрес таблицы перемещений в файле
WORD e_ovno;// Номер перекрытия
WORD e_res[4];// Зарезервировано
WORD e_oemid; // OEM идентификатор (для e_oeminfo)
WORD e_oeminfo;// Информация OEM; специфично для e_oemid
WORD e_res2[10];// Зарезервировано
LONG e_lfanew; }// Адрес следующего заголовка в файле
}IMAGE DOS HEADER, РIMAGE DOS HEADER;

Наиболее поучительна в этом отношении система RT-11, в которой существуют загружаемые модули обоих типов. Обычные программы имеют расширение sav, представляют собой абсолютные загружаемые модули и грузятся всегда с адреса 01000. Ниже этого магического адреса находятся векторы прерываний и стек программы. Сама операционная система вместе с драйверами размещается в верхних адресах памяти. Естественно, вы не можете загрузить одновременно два sav-файла.

Однако, если вам обязательно нужно исполнять одновременно две программы, вы можете собрать вторую из них в виде относительного модуля: файла с расширением rel. Такая программа будет загружаться в верхние адреса памяти, каждый раз разные, в зависимости от конфигурации ядра системы, количества загруженных драйверов устройств и других rel-модулей (рис. 3.5).

Иллюстрированный самоучитель по теории операционных систем › Загрузка программ › Относительная загрузка
Рис. 3.5. Распределение памяти в RT-11 с одним загруженным sav-файлом и двумя rel-файлами

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.