Теорія операційної системи

:: Меню ::

Головна
Представлення даних в обчислювальних системах
Машинні мови
Завантаження програм
Управління оперативною пам'яттю
Сегментна і сторінкова віртуальна пам'ять
Комп'ютер і зовнішні події
Паралелізм з точки зору програміста
Реалізація багатозадачності на однопроцесорних комп'ютерах  
Зовнішні пристрої
Драйвери зовнішніх пристроїв
Файлові системи
Безпека
Огляд архітектури сучасних ОС

:: Друзі ::

Карта сайту
 

:: Статистика ::

 

 

 

 

 

Відносне завантаження

Відносний спосіб завантаження полягає в тому, що ми завантажуємо програму кожного разу з нової адреси. При цьому ми повинні набудувати її на нові адреси, а для цього нам треба пригадати матеріал попередньої глави і зрозуміти, що ж саме в програмі прив'язано до адреси завантаження.
При використанні в коді програми абсолютної адресації ми повинні знайти адресні поля всіх команд, що використовують таку адресацію, і перерахувати ці адресні поля з врахуванням реальної адреси завантаження (мал. 3.3). Якщо в коді програми застосовувалися побічно-регістровий, базовий і ба-зово-индексный режими адресації, слід знайти ті місця, де в регістр завантажується значення адреси (мал. 3.4).


Мал. 3.3. Переміщення коди, що використовує абсолютну адресацію

Мал. З.4. Переміщення коди, що самостійно перезавантажує базові регістри

Складність тут в тому, що якщо абсолютні адресні поля можна знайти аналізом код команд (деассемблірованієм), то значення в адресний регістр може завантажуватися задовго до власне адресації, причому, як ми бачили в прикладах коди для процесора SPARC, Формування значення регістра може відбуватися і по частинах. Без допомоги програміста або компілятора (у цій главі ми не розрізнятимемо написаний на асемблері або код, що компілює, а того, КТО генерував код, називатимемо програмістом) вирішити питання про те, яка з команд завантажує в регістр скалярне значення, а яка -будущий адреса або частина адреси, неможливо. Та ж проблема виникає у випадку, якщо ми використовуємо як покажчик вічко статично ініциалізованних даних (приклад 3.3).

Приклад 3.3. Приклади статично ініциалізованних покажчиків в с

int buf[20] *bufptr=buf;
char * message="no message defined yet\n";
void do_nothing_hook(int);
void (*hook)(int)=do_nothing_hook;

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

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

push dst seg ; Це і буде засланням на абсолютну адресу
push dst_offs
retf

На практиці сприяння програміста завантажувачу полягає в тому, що програміст старається без необхідності не використовувати в адресних полях і як значення адресних регістрів довільні значення (необхідність в цьому може виникати при адресації системних структур даних або зовнішніх пристроїв, розташованих по фіксованих адресах). Замість цього, програміст застосовує асемблерні символи, відповідні адресам.
Асемблер при кожному засланні на такий символ генерує не лише "заготівку" адреси в коді, але і запис в таблиці переміщень (relocation table). Цей запис зберігає місце заслання на такий символ в коді або даних. Якщо в засланні використовується лише частина адреси, як в командах sethi %10, %hi(addr) процесора SPARC, або move ах, segment addr Процесора 8086, ми запам'ятовуємо і цей факт.
Як "заготівка" адреси зазвичай використовується змішення об'єкту, що адресується, від початку програми. При налаштуванні програми на реальну адресу завантаження нам, таким чином, необхідно пройти по всіх об'єктах, перерахованих в таблиці переміщень, і перемістити кожне із заслань — сформувати із заготівки адресу.
Файл, що містить таблицю переміщень, набагато складніше за абсолютний завантажуваний модуль і носить назву відносного або переміщуваного завантажувального модуля. Саме такий формат мають ехе-файлы в системі MS DOS (приклад 3.5).

Приклад 3.5. Заголовок ЕХЕ-файла MS DOS. Цитується по WINT.H з постачання | ; 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-файлами


:: Реклама ::

заточка маникюрного инструмента район

 

:: Посилання ::


 

 

 


Copyright © Kivik, 2017