1   2   3   4   5   6   7   8
Ім'я файлу: ЗВІТ КУРСАЧА - РЕЗИДЕНТНИЙ КАЛЬКУЛЯТОР.docx
Розширення: docx
Розмір: 511кб.
Дата: 05.11.2021
скачати

2.2. Функція tsrinit


Функція tsrinit виконує всі дії, необхідні для ініціалізації резидентної програми.

Перш за все, ця функція резервує область пам'яті для стека, який буде використаний в момент активізації резидентної програми.

Ось відповідний фрагмент коду:

wk_ptr = malloc (HEAP_RESERVED);

if (wk_ptr == NULL) return 0;
tsr_stack = malloc (STACK_SIZE);

if (tsr_stack == NULL) return 0;

tsr_stack + = STACK_SIZE;

free (wk_ptr);

На перший погляд може здатися, що тут ми виконуємо дивні дії - спочатку замовляємо блок пам'яті, який має розмір HEAP_RESERVED, а потім відразу ж віддаємо його, так і не використавши жодного разу. Проте, такі дії мають певний сенс.

Повернувшись до рис. 2.1, зауважимо, що перед стеком повинна розташовуватися область пам'яті HEAP. Вона потрібна для роботи функцій динамічного виділення пам'яті (і не тільки для цих функцій). Тому область стека резидентної програми повинна бути розташована нижче, як це показано на рис. 2.1.

Насправді викликаючи функцію malloc в перший раз, ми резервуємо пам'ять для області HEAP. Після другого виклику функції malloc буде виділена область пам'яті розміром STACK_SIZE, розташована відразу після області HEAP. Така область підходить для стека резидентної програми.

Так як стек росте в напрямку до початку пам'яті, ми запам'ятовуємо в змінної tsr_stack адреса нижньої межі отриманої області (точніше кажучи, компоненту зсуву адреси стека, придатну для завантаження в регістр SP).

Коли резидентна програма активізується, регістри SS: SP будуть завантажені так, щоб вказувати на виділену нами область стека. При цьому перед стеком буде розташована область пам'яті, що має розмір HEAP_RESERVED. Вона буде виконувати роль області HEAP, забезпечуючи можливість використання стандартних функцій бібліотеки С.

Після всіх цих маніпуляцій функція tsrinit отримує і зберігає покажчик на так званий прапор InDos, викликаючи для цього функцію getInDosFlag. Цей прапор встановлюється перед початком використання будь-яких функцій переривань MS-DOS і скидається після завершення виконання зазначених функцій. Наша резидентна програма використовує прапор InDos для визначення можливості активізації.

Далі функція tsrinit зберігає старі значення ряду векторів переривань і установлює нові обробники для цих переривань.

На завершення функція звільняє блок пам'яті, виділений для змінних середовища в сегменті PSP:

FP_SEG (fp) = _psp;

FP_OFF ​​(fp) = 0x2c;

_dos_freemem (* fp);

Для цього повну адресу вивільняється блоку пам'яті формується в покажчику fp. Нагадаємо, що сегментна компонента адреси блоку змінних середовища знаходиться в PSP. Зсув відповідного слова одно 0x2c. Сегментна адреса блоку PSP знаходиться в глобальній змінній з ім'ям _psp.

2.3. Функція InDos


Функція tsrinit викликає функцію getInDosFlag, яка одержує і зберігає покажчик на прапор InDos, а також на прапор оброблювача критичних помилок. Останній встановлюється в тому випадку, коли MS-DOS обробляє критичну помилку вводу / виводу.

Резидентна програма не повинна активізуватися, якщо встановлені зазначені вище прапори. Однак є один виняток - якщо викликано переривання INT 28h, можна виконувати активізацію резидентної програми.

Отримати покажчик на прапор InDos нескладно - для цього достатньо скористатися недокументованою функцією 34h переривання INT 21h:

regs.h.ah = 0x34;

intdosx (& regs, & regs, & sregs);

FP_SEG (indos_ptr) = sregs.es;

FP_OFF ​​(indos_ptr) = regs.x.bx;

Шуканий адресу повертається в регістрах ES: BX.

У MS-DOS ранніх версій (до версії 3.0) прапор оброблювача критичних помилок був розташований безпосередньо перед прапором InDos. У версії 3.0 його перенесли на нове місце - відразу після прапора InDos. В обох випадках розташування цих прапорів не було вказано в документації.

Для з'ясування розташування прапора оброблювача критичних помилок в MS-DOS нових версій ви повинні використовувати недокументовані функцію 5Dh переривання INT 21h:

regs.x.ax = 0x5D06;

intdosx (& regs, & regs, & sregs);

FP_SEG (crit_err_ptr) = sregs.ds;

FP_OFF ​​(crit_err_ptr) = regs.x.si;

Ця функція поверне покажчик на прапор оброблювача критичних помилок в регістрах DS: SI.

РОЗДІЛ ІІІ

3.1. Установка обробників переривань


Останнє, що робить функція tsrinit перед поверненням управління - вбудовування оброблювачів деяких переривань. При цьому для забезпечення можливості вивантаження резидентної програми з пам'яті зберігаються старі значення змінних векторів переривань.

Перед тим як приступити до зміни векторів переривань, функція tsrinit забороняє апаратні переривання, викликаючи функцію _disable. Після того як зміна векторів переривань завершено, викликається функція _enable, роздільна обробку апаратних переривань:

_disable ();

old_int1c = _dos_getvect (0x1C);

old_int2f = _dos_getvect (0x2F);

old_int8 = _dos_getvect (8);

old_int9 = _dos_getvect (9);

old_int13 = _dos_getvect (0x13);

old_int28 = _dos_getvect (0x28);

get_int_13 ();
_dos_setvect (0x1C, (fptr) new_int1c);

_dos_setvect (0x2F, (fptr) new_int2f);

_dos_setvect (8, (fptr) new_int8);

_dos_setvect (9, (fptr) new_int9);

_dos_setvect (0x13, (fptr) new_int13);

_dos_setvect (0x28, (fptr) new_int28);

_enable ();

Обробники всіх переривань, за винятком переривання INT 13h, складені мовою С. Так як переривання INT 13h повертає результат виконання операцій в регістрі прапорів, відповідний обробник зручніше скласти на мові асемблера.

1   2   3   4   5   6   7   8

скачати

© Усі права захищені
написати до нас