Розрахункова робота
Резидентні програми у ІBM PC.
Мета: Вивчення принципів побудови та функціонування резидентних програмам.
Програми, що повинні постійно знаходитись в пам'яті і миттєво реагувати на події, що відбуваються в обчислювальній системі, носять назву резидентних в пам'яті (Terminate but Stay Resident, TSR). Резидентною може бути програма, як .COM, так і .EXE формату, одначе, оскільки резидентна програма повинна бути максимально компактною, найчастіше використовується .COM формат.
Резидентні програми, як правило, складаються з двох частин - ініціалізуючої та робочої (резидентної). В тексті програми резидентна частина розміщується на початку, ініціалізуюча – за нею.
Під час першого виклику програма повністю завантажується в пам'ять і управління передається до секції ініціалізації, яка заповнює або модифікує вектори переивань, настроює програму на конкретні умови роботи і за допомогою переривання DOS INT 21h з функцією 31h завершує програму, залишаючи в пам'яті її резидентну частину. Розмір резидентної частини (в параграфах) передається DOS в регістрі DX. Вказувати при цьому сегментну адресу програми немає необхідності, оскільки він відомий DOS.
Для визначення розміру резидентної секції її можна завершити конструкцією вигляду "res_size equ $ - your_proc", де your_proc - адреса початку програми, а при виклику функції 31h в регістр DX переслати результат обчислення виразу (res_size + 10Fh)/16.
Функція 31h, закріпивши за резидентною програмою необхідну для її функціонування пам'ять, передає управління командному процесору COMMAND.COM і обчислювальна система, таким чином, повертається у вихідний стан. Наявність програми, резидентної в пам’яті, ніяк не відбивається на ході основного обчислювального процесу за виключенням того, що зменшується об’єм доступної йому пам’яті. Одночасно може бути завантажено декілька резидентних програм.
Для того, щоб активізувати резидентну програму, їй необхідно передати управління і, можливо, параметри. Запустити резидентну програму можна наступними способами:
викликати її оператором CALL як підпрограму;
потребує наявності в пам'яті поточно активної програми, що, очевидно, повинна утворювати з викликаючою програмою єдиний комплекс із наперед визначеним інтерфейсом взаємодії (міжпрограмним інтерфейсом). Оформивши у вигляді резидентної програми процедури виконання функцій, спільних для обох вищезгаданих програм, можна спростити структуру і об’єм такого багатопрограмного комплексу.
використати механізм асинхронних (апаратних) переривань;
асинхронна активізація зовнішнім перериванням (наприклад, від таймера, клавіатури, послідовного порту та іншого периферійного обладнання), широко використовується резидентами BIOS, а також багатьма прикладними програмами: трансляторами клавіатурної розкладки, калькуляторами та ін.
за допомогою синхронного (програмного) переривання;
здійснюється за допомогою команди INT - характерна для встановлюваних драйверів DOS, програм обслуговування дисків та ін.
Крім того, спеціально для взаємодії з резидентними програмами в DOS передбачено мультиплексне переривання 2Fh.
Типова структура резидентної програми:
text segment 'code'
assume cs:text, ds:text
org 100h
myproc proc far
jmp init ; перехід на секцію ініціалізації
; дані резидентної частини
…
entry: ; текст резидентної частини
…
myproc endp
res_size equ $-myproc ; розмір в байтах резидентної частини
init proc ; секція ініціалізації
…
mov DX,(res_size + 10Fh)/16 ; розмір в параграфах
mov AX,3100h ; функцыя "завершити але залишити в пам'яті"
int 21h
init endp
text ends
end myproc
При першому способі запуску програми з клавіатури управління передається на початок процедури myproc (перший байт після PSP). Командою JMP здійснюється перехід на секцію ініціалізації, в якій, готуються умови для подальшої активізації програми в резидентному стані. Останніми стрічками секції ініціалізації викликається функція 31h, що виконує завершення програми залишаючи її вказану частину в пам'яті. З метою економії пам'яті секція ініціалізації розташовується в кінці програми і відкидається при її завершенні. Перед початком виконання резидент повинен зберегти всі викорстані ним регістри, а по завершенні - відновити їх.
Для звертання до резидентної програми з транзитної можна використати область міжзадачних зв'язків, що є частиною області даних BIOS і знаходиться за адресами 40h:F0h….40h:FFh. Ця область не використовується системою і призначена спеціально для комунікацій програм користувача. За допомогою області міжзадачних зв'язків можна здійснити як виклик резидентної програми, так і передачу параметрів (зручніше передавати не самі параметри, а їх адреси). По ходу виконання секції ініціалізації майбутня резидентна програма пересилає у вказані комірки області міжзадачних зв'язків адресу своєї точки входу, наприклад, в слово 40h:F0h відносну адресу команди з міткою entry, а в слово 40h:F2h - вміст сегментного регістру CS. Транзитна програма для передачі управління резидентній настроює регістр ES на початок області даних BIOS і виконує команду дальнього виклику
call dword ptr ES:0F0h
В цьому випадку резидентна програма повинна бути задекларована, як дальня процедура (myproc prc far) і завершуватись командою RET дальнього повернення.
Якщо для резидентної програми необхідно передати параметри виконання, їх початкова адреса (або, по необхідності, адреса цілого списку адрес) заноситься транзитною програмою в іншу обумовлену комірку області міжзадачних зв'язків, наприклад, двослівну комірку 40h:F4h. В цьому випадку резидентна програма переносить, наприклад, в регістр SI відносну адресу параметра із комірки 40h:F4h, а в регістр DS – сегментну адресу параметра з комірки 40h:F6h і після цього відбирає самі параметри командами типу
mov AX,DS:[SI]
mov BX,DS:[SI+2]
…
Примітка: перед початком виконання резидентна програма повинна зберегти всі використовувані нею регістри, а перед завершенням – відновити їх.
Більш елегантним методом передачі управління і параметрів резидентній програмі є використання вільних векторів, наприклад, 60h…66h. В процесі ініціалізації резидентна програма пересилає свою адресу у вільний вектор:
mov AX,00
mov ES,AX
mov ES:180h, offset entry ; адреса вектора 60h
mov ES:182h,CS
тоді для активізації резидентної програми в транзитній програмі достатньо виконати команду
int 60h
В цьому випадку резидентна програма повинна закінчуватись командою IRET. Адреси параметрів можна передавати через інші вільні вектори (наприклад, 61h і 62h), або область міжзадачних зв'язків.
Якщо резидентна програма повинна запускатись безпосередньо з клавіатури, незалежно від наявності чи відсутності транзитної програми, необхідно скористатись апаратним вектором переривання типу 9 (див. Лабораторна робота № 6).
Для взаємодії з паралельними процесами (наприклад, резидентними програмами) в MS-DOS передбачено стандартний інтерфейс – переривання 2Fh. Перед викликом цього переивання слід помістити в регістр AH номер функціх, а в регістр AL – номер підфункції. Функції 00h…BFh зарезервовані для MS-DOS; функції C0h…FFh зарезервовані для прикладних програм. Якщо за допомогою переривання 2Fh передбачається передача до резидентної програми та отримання з неї великої кількості параметрів, можна використати інші регістри, наприклад, DS:DX / DS:SI і передавати через них адреси списківпараметрів.
Згідно системних домовленостей переивання 2Fh повертає в регістрі AL стан резидентної програми:
AL=0 – програму не встановлено (немає в пам’яті) і її можна встановити;
AL=1 – програму не встановлено (немає в пам’яті) і її не можна встановити;
AL=FFh – програму встановлено.
У випадку помилки необхідно встановити прапорець CF, а в регістрі AX повернути код помилки.
Для того, щоб прикладна програма відповідала на переивання 2Fh, слід включити в неї прикладний обробник одної.декількох з функцій цього переривання. Тоді виклик відповідної цього переривання в будь-якій транзитній програмі дозволить організувати взаємодію із завантажуваною резидентною програмою.
Типова структура резидентної програми з обробником переривання 2Fh:
;initialization
;store the address of 2Fh to be able to use its fns
init: mov AH,35h ;get vector
mov AL,2Fh ;vector type
int 21h ;
mov word ptr old2fh,BX ;store 2Fh vector in old2fh
mov word ptr old2fh+2,ES
;set our handler address into 2Fh
mov AH,25h ;set vector
mov AL,2Fh ;vector type
lea DX,new2fh
int 21h
;other action for installation
… …
;terminate and stay resident using 31h (DOS fn 21h)
… …
;2Fh handler, contained in a resident section of our TSR
… …
;work section
entry:
…
iret
;your 2Fh (fn C0h) handler
new2fh: cmp AH,0C0h ;our fn?
je C0h ;yes
jmp CS:oldfh ;no, proceed to system handler
;possibly, AL analysis & jump to other fns’ handler – any other actions – whatever you wish
… …
iret
Після того, як програма-кандидат в резиденти завантажується і залишається в пам’яті за допомогою функції MS-DOS 31h, управління передається COMMAND.COM, який очікує наступних команд оператора.
Для захисту резидентної програми від багатократного завантаження можна включити в модуль програми деякий довільний код (сигнатуру) і перевіряти його наявність в пам'яті в процесі ініціалізації. Якщо резидентна програма користувача ще не встановлена, в векторі 09h зберігається адреса системного обробника, в якому немає сигнатури. Якщо ж резидентна програма встановлена - в пам'яті є сигнатура.
Структура програми, що перевіряє наявність свого поточно активного екземпляру в пам’яті, може виглядати так:
org 100h ;.COM program
myproc proc
jmp init ;initialization section
mark dw 1234h ;signature
;work section
entry:
…
init: mov AX,3509h ;let this be the handler for keyboard interrupt
int 21h ;
sub BX,2 ;ES:BX – contents of the 09 vector
;BX->entry-2, that is mark, is our program is ;already loaded
cmp word ptr ES:[BX],1234h
je installed ;signature found
;signature found. Proceed with initialization.
;terminate and stay resident
… …
installed:
;in case of error
…
mov AX,4C01h ;terminate with error code & not stay resident
int 21h
Слід відзначити - якщо після ініціалізації і запуску описаної програми буде завантажена інша резидентна програма обробки того ж самого переривання – розглянута методика є неефективною, оскільки в векторі переривання буде знаходитись адреса іншої програми (завантаженої останньою), в якій сигнатура відсутня.
Інший метод захисту пов’язаний з таким захистом може виглядати таким чином:
;initialization
;check for presence of previously installed instance
init: mov AX,0C000h ;fn C0h, subfn 00h
int 2Fh ;our handler has to return AL=FFh
cmp AL,0FFh ;istalled?
je installed ;yes, proceed to exit
;not installed. Proceed with initialization: set your own handler for
;2Fh, load other vectors, terminate and stay resident
… …
;2Fh handler, contained in a resident section of our TSR
cmp AL,0C000h ;our fn & subfn?
jne go_2fh_syshandler ;no, proceed to system
;handler for 2Fh
mov AL,0FFh ;installed already, return FFh to
iret ;initialization section
go_syshandler:
jmp CS:old2fh ;jump to 2Fh system handler
Приклад побудови резидентної програми:
Дана програма при активованому режимі <Caps Lock> динамічно заміняє вивід образів чисел на вивід псевдографічних символів, що може виявитись зручним для малювання рамок, таблиць, тощо при роботі в символьному редакторі, що самостійно не забезпечує подібної функціональності.
; отримати відкомпільований модуль int83.com
; запустити на виконання програму Keyukr
; запустити на виконання запустити іnt83.com
; завершити роботу через <Alt-Q>.
.model tiny
.code
;визначення константи
ALT_Q EQU 1000h
ORG 100h
myproc PROC far
jmp init
; дані резидентної частини
old_09h DD 0
old_stack DD 0
mesr DB 'ALT/Q - Resident uninstalled',10,13
mesrlen EQU $-mesr
borders DB 0,0,'│','┤','┐','└','┴','┬','├','─','┼','┘','┌'
; резидентна секція програми
new_09h:
cli
; виклик старого обробника переривання
pushf
call dword ptr cs:old_09h
;перемикання стеку
mov word ptr cs:old_stack,sp
mov word ptr cs:old_stack+2,ss
mov sp,cs
mov ss,sp
mov sp,offset cs:TOS
push bp
push ax
push bx
push cx
push dx
push ds
push es
mov ax,cs
mov ds,ax
mov ax,40h
mov es,ax
; обробка символа з кільцевого буфера без прямого видобування
mov bx,es:1ah
mov ax,es:[bx]
cmp ax,ALT_Q
je altq
cmp ah,2
jb home
cmp ah,12
ja home
; скен-код - в заданих межах. Перевірити, чи активовано <Caps Lock>?
test byte ptr es:17h,40h
jz home
; <Caps Lock> активовано + натиснуто клавішу <1/!>..<-/_>
push bx
mov bx,offset cs:borders
xchg ah,al
xlat
pop bx
mov byte ptr es:[bx],al
; повернення до перерваної програми
home:
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
pop bp
; відновлення стеку
mov sp,word ptr cs:old_stack+2
mov ss,sp
mov sp,word ptr cs:old_stack
sti
iret
altq:
; завершити роботу обробника / вивести повідомлення
mov ax,cs
mov es,ax
mov ah,13h
mov al,1
mov bx,0020h
mov cx,mesrlen
mov dh,16
mov dl,22
mov bp,offset cs:mesr
int 10h
; відновити вектор без застосування функцій DOS
mov ax,0
mov es,ax
mov ax,word ptr cs:old_09h
mov word ptr es:24h,ax
mov ax,word ptr cs:old_09h+2
mov word ptr es:26h,ax
jmp home
; область стеку
Stack_Array DW 200 dup(0)
TOS LABEL word
endres EQU $-myproc
; секція ініціалізації
init:
; прочитати та зберегти старий вектор переривання
mov ax,3509h
int 21h
mov word ptr cs:old_09h,bx
mov word ptr cs:old_09h+2,es
; встановити новий вектор
mov ax,cs
mov ds,ax
mov ax,2509h
mov dx,offset cs:new_09h
int 21h
; вивід повідомлення
mov ax,cs
mov ds,ax
mov ah,40h
mov bx,1
mov cx,meslen
mov dx,offset cs:mes
int 21h
; залишити резидентним
mov ax,3100h
mov dx,(endres+10Fh)/16
int 21h
; дані ініціалізуючої частини
mes DB ' Resident installed !',10,13
DB ' ALT/Q - uninstalled',10,13
meslen EQU $ - mes
myproc ENDP
END myproc
ЗАВДАННЯ:
Створити резидентну програму, що реалізує вказаний викладачем варіант завдання. Програму оформити у вигляді .COM файлу.
Запустити створену програму та задокументувати результати її виконання.
Скласти звіт про виконану роботу, який повинен містити наступні частини:
титульний аркуш; (1ст.)
зміст; (1ст.)
вступ (коротка характеристика завдання); (1ст.)
теоретичні відомості про принципи та методи побудови резидентних програм; (4 ст)
опис та пояснення алгоритму роботи резидентної програми; (2-3ст.)
повна блок-схема програми, реалізованої згідно варіанту;
лістинг прогорами та результати її виконання.
висновки (1ст.).
Варіанти завдання:
Див.файл Variants.doc
ЛІТЕРАТУРА:
1.Р.Джордейн.Справочник програмиста персональных компъютеров типа ІBM PC XT и AT. - M."Финансы и статистика",1992,стор.13-31.
2.Л.О.Березко,В.В.Троценко. Особливості програмування в турбо-асемблері. -Киів,НМК ВО,1992.
3.Л.Дао. Программирование микропроцессора 8088.Пер.с англ.-М."Мир",1988.
4.П.Абель.Язык ассемблера для ІBM PC и программирования. Пер. з англ.-М.,"Высшая школа",1992.