Относительная загрузка Относительный способ загрузки
состоит в том, что мы загружаем программу каждый раз с нового адреса.
При этом мы должны настроить ее на новые адреса, а для этого нам надо
вспомнить материал предыдущей главы и понять, что же именно в программе
привязано к адресу загрузки.
Рис. 3.3. Перемещение кода, использующего абсолютную адресацию Рис. З.4. Перемещение кода, самостоятельно перезагружающего базовые регистры Сложность здесь в том, что если абсолютные адресные поля
можно найти анализом кодов команд (деассемблированием), то значение в
адресный регистр может загружаться задолго до собственно адресации, причем,
как мы видели в примерах кода для процессора SPARC, Формирование значения
регистра может происходить и по частям. Без помощи программиста или компилятора
(в этой главе мы не будем различать написанный на ассемблере или компилированный
код, а того, кто генерировал код, будем называть программистом) решить
вопрос о том, какая из команд загружает в регистр скалярное значение,
а какая -будущий адрес или часть адреса, невозможно. Та же проблема возникает
в случае, если мы используем в качестве указателя ячейку статически инициализованных
данных (пример 3.3). int buf[20], *bufptr=buf; Довольно легко построить и пример кода, в котором адресация происходит вообще без явного использования каких-либо регистров, во всяком случае, без загрузки в них значений (пример 3.4). Пример 3.4. Реализация косвенного перехода по адресу dst_seg:dst_offs push dst seg ; Это и будет ссылкой на абсолютный адрес На практике содействие программиста загрузчику состоит
в том, что программист старается без необходимости не использовать в адресных
полях и в качестве значений адресных регистров произвольные значения (необходимость
в этом может возникать при адресации системных структур данных или внешних
устройств, расположенных по фиксированным адресам). Вместо этого, программист
применяет ассемблерные символы, соответствующие адресам. Пример 3.5. Заголовок ЕХЕ-файла MS DOS. Цитируется по WINT.H из поставки | ; MS Visual C++ v6.0 (перевод комментариев автора) #define IMAGE_DOS_SIGNATURE Ox4D5A // MZ Наиболее поучительна в этом отношении система RT-11,
в которой существуют загружаемые модули обоих типов. Обычные программы
имеют расширение sav, представляют собой абсолютные загружаемые модули
и грузятся всегда с адреса 01000. Ниже этого магического адреса находятся
векторы прерываний и стек программы. Сама операционная система вместе
с драйверами размещается в верхних адресах памяти. Естественно, вы не
можете загрузить одновременно два sav-файла. Рис. 3.5. Распределение памяти в RT-11 с одним загруженным sav-файлом и двумя rel-файлами |