Міністерство освіти України p>
Одеська державна академія холоду p>
Інститут інформаційних технологій p>
Кафедра «Інформаційних систем» p>
Розробка резидентного обробника переривань від клавіатури p>
Курсовий проект з дисципліни p>
«Системи програмування та операційні системи» p>
Керівник Ненов А. Д. Виконавець p>
Ст. гр. 333А Лазанюк
А. С. p>
зач. книжка № 983214 p>
Захищений з оцінкою _____________________ p>
(особистий підпис)
_______________ p>
м. Одеса 2000 p>
Зміст: p>
1. Завдання ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... .2 p>
2. Короткі теоретичні відомості p>
1. Резидентний обробник переривань ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 3 p>
2. Захист резидентної програми від повторної установки ... ... ... ... ... ... ... ... ... ... ... ... ... .. 5 p>
3. Вивантаження резидентної програми з пам'яті ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 8 p>
4. Перехоплення переривань ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 11 p>
5. Оброблювач переривань ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 12 p>
6. Переривання від зовнішніх пристроїв ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... .. 12 p>
7. Резидентний обробник переривань від клавіатури з підключенням до системного обробника ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... .14 p>
3. Опис програми p>
1. Опис для користувача ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 19 p>
2. Опис для програміста ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... .20 p>
3. Лістинг програми ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... .. ... .24 p>
4. Рекомендації щодо поліпшення ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 32 p>
4. Список використаної літератури ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... .. ... .33 p>
1. Завдання p>
Розробка резидентного обробника переривань від клавіатури зпідключенням до системного. Даний обробник повинен робити записскан-кодів всіх натискає клавішу, а також фіксувати байт прапорівклавіатури при кожному натисканні. Оброблювач повинен мати механізм вивантаження зоперативної пам'яті вбудований в нього самого. Також програма повинна матизахист від повторної установки в оперативну пам'ять. p>
2. Короткі теоретичні відомості p>
2.1. Резидентний обробник переривань p>
Великий клас програм, що забезпечують функціонування обчислювальноїсистеми (драйвери пристроїв, програми шифрування та захисту даних,русифікатори, що обслуговують програми типу електронних блокнотів абокалькуляторів тощо), повинні постійно перебувати в пам'яті й швидкореагувати на запити користувача або на якісь події, що відбуваються вобчислювальної системи. Такі програми мають назви програм,резидентних у пам'яті (Terminate and Stay Resident, TSR), або просторезидентних програм. Зробити резидентної можна як програму типу СОМ,так і програму типу
ЕХЕ, але через те, що резидентна програма повинна бути максимальнокомпактною, найчастіше як резидентних використовують програми типу
СОМ. P>
Розглянемо типову структуру резидентної програми та системні засобизалишення її в пам'яті після ініціалізації (рис. 2.1).text segment 'code' assume CS: text, DS: text org 100h main proc jmp init; Перехід на секцію ініціалізації p>
; Дані резидентної секції програми p>
. . . entry:; Текст резидентної секції програми p>
. . . p>
main endp p>
init proc; Секція ініціалізації p>
. . . p>
mov DX, (init-main +10 Fh)/16; Paзмер в параграфах mov АН, 3100h; функція "Завершити і залишити в int 21h; пам'яті" init endp text ends end main p>
Рис 2.1. Типова структура резидентної програми. P>
Програма пишеться у форматі СОМ, тому в ній передбачається лишеодин сегмент, з яким зв'язуються сегментні регістри CS і DS; на початкусегмента резервується l00h байт дня PSP.
При запуску програми з клавіатури управління передається (відповідноз параметром директиви end) на початок процедури main. Командою jmp відразу жздійснюється перехід на секцію ініціалізації, яка може бутиоформлена у вигляді окремої процедури чи входити до складу процедури main.
У секції ініціалізації, зокрема, готуються умови для роботипрограми вже в резидентним стані. Останніми рядками секціїініціалізації викликається функція DOS 31h, яка виконує завершенняпрограми з залишенням в пам'яті зазначеної її частини. Ця функція не можезалишати резидентними програми розміром більше 64 Кб, але багатопрограми, написані на асемблері, відповідають цій умові. Так якрезидентні програми зменшують обсяг основної пам'яті, їх завжди пишуть наасемблері і оптимізують для досягнення мінімального розміру.
Розмір резидентної частини програми (у параграфах) передається DOS врегістрі DX. Визначити розмір резидентної секції можна, наприклад,наступним чином. До різниці зсувів mil-main, яка дорівнює довжинірезидентної частини програми в байтах, додається розмір PSP (l00h) і щечисло 15 (Fh) для того, щоб після цілочисельного поділу на 16 результатбув заокруглений в більшу сторону. p>
З метою економії пам'яті секція ініціалізації розташовується я кінціпрограми та відкидається при її завершенні. p>
Точка входу (main при завантаженні jmp init p>
. Резидентні p>
(поля даних
Резидентна частина p>
Точка входу (entry програми при виклику. Резидентні p>
(коди iret init p>
. Секція p>
(ініціалізації Завершенняпрограми p>
Функція DOS 31h (з складанням у пам'яті p>
її резидентної частини p>
Рис. 2.2 Взаємодія елементів резидентної програми. p>
Функція 31h , закріпивши за резидентну програму необхідну для їїфункціонування пам'ять, передає управління командному процесору іобчислювальна система переходить в початковий стан. Наявність програми,резидентного в пам'яті, ніяк не відбивається на ходу обчислювального процесу,за винятком того, що зменшується обсяг вільної пам'яті. Одночасно впам'ять може бути додано будь-яке число резидентних програм. p>
На рис. 2.2 показані елементи резидентної програми та їх взаємодія. P>
Будь-яка резидентна програма має принаймні дві точки входу. Призапуску з клавіатури програми типу. СОМ керування завжди передається наперший байт після PSP (IP = l00h). Тому практично завжди першою командоюрезидентної програми є команда jmp, що передає керування на початоксекції ініціалізації. p>
Після відпрацювання функції DOS 31h програма залишається в пам'яті в пасивномустані. Для того, щоб активізувати резидентну програму, їй требаякось передати управління і, можливо, параметри. Викликати до життярезидентну програму можна різними способами, але найбільш вживаноює механізм апаратних чи програмних переривань. У цьому випадку всекції ініціалізації необхідно заповнити відповідний вектор адресоюрезидентної частини програми (точка entry на рис. 2.2). Адреса entry утворюєдругу точку входу в програму, через яку здійснюється їїактивізація. Очевидно, що резидентна секція програми повинназакінчуватися командою виходу з переривання iret. p>
Поля даних резидентної частини програми перемістилися в початок програмипісля команди imp. Це досить природне місце дня резидентних даних,тому що і при першому запуску, і при активізації сюди ніколи не будепередано управління. При заповненні в секції ініціалізації вектор невиникає проблем з перенастроюванням регістра DS, так як у програмі типу
СОМ всі регістри вказують на єдиний сегмент програми. У секціїініціалізації передбачений, як це зазвичай робиться, виведення на екранповідомлення про завантаження програми в пам'ять. p>
Після запуску програми вона залишається в пам'яті і, активізуючись фактичноапаратними переривань від клавіатури (а точніше - програмою BIOS,керуючі апаратними переривань від клавіатури). p>
2.2. Захист резидентної програми від повторної установки p>
Як правило, в секції ініціалізації завантажуються вектори переривань, черезякі буде активізуватися програма. Останніми рядками секціїініціалізації викликається функція DOS 31h, яка виконує завершенняпрограми з залишенням в пам'яті її резидентної частини. p>
Якщо запустити програму з клавіатури повторно, в пам'ять буде завантаженаі залишиться резидентної її друга копія. Це погано не тільки тому, щодаремно витрачається пам'ять, більш неприємним є вторинний перехопленнятих же векторів. Якщо резидентний програма після її активізації незвертається до старого вмісту перехоплених нею векторів, то друга копіяповністю позбавить першого працездатності, і тоді повторна завантаженняпризведе тільки до витрачання пам'яті. Якщо, однак, як це зазвичай і маємісце, резидентна програма в процесі своєї роботи передасть управліннястарому обробникові перехопленого нею переривання, то нова копіярезидентної програми, що зберегла в процесі ініціалізації адреса першогокопії в якості вмісту перехоплює вектор, буде при кожнійактивізації викликати і першу копію. У результаті резидентна програмабуде фактично виконуватися при кожному виклику двічі. У багатьох випадкахтаке повторне виконання порушить правильну роботу програми. Томуобов'язковим елементом будь-якої резидентної програми є процедуразахисту її від повторного завантаження, або, як кажуть, установки. p>
Найбільш поширеним методом захисту резидентної програми відповторної установки є використання переривання 2Fh, спеціальнопризначеного для зв'язку з резидентними програмами. Коли Ви робите цьогопереривання в регістрі АН задається номер функції (від 00h до FFh), а врегістрі AL - номер підфункції (у тому ж діапазоні). 00h - 7Fhзарезервовано для DOS/Windows 0B8h - 0BFh зарезервовано для мережевихфункцій 0C0h - 0FFh відводиться для програм. p>
Для того, щоб резидентна програма могла відгукнутися на викликпереривання int 2Fh, у неї повинен бути обробник цього переривання.
Фактично всі резидентні програми, як системні, так і прикладні,мають такі обробники, через які здійснюється не тільки перевірка наповторну установку, але і взагалі зв'язок з резидентну програму: змінарежиму її роботи або отримання від неї в транзитну програму якихосьпараметрів. Завдання дії, яке належить виконати обробниковіпереривання 2Fh конкретної резидентної програми, здійснюється за допомогоюномера підфункції, що поміщаються перед викликом переривання в регістр AL p>
Таким чином, обробник переривання 2Fh резидентної програми повинен,перш за все, перевірити номер функції в регістрі АН; при виявленні
"своєї" функції обробник аналізує вміст регістру AL і виконуєвитребувані дії, після чого командою iret передасть управліннящо викликала його програмі. Якщо, однак, обробник виявив в регістрі АН
"чужу" функцію, він повинен командою jmp CS: old_2fh передати управління поланцюжку тому обробникові, адреса якого був раніше у векторі 2Fh. Урезультаті виклик int 2Fh з будь-якої програми буде проходити по ланцюжкучерез всі завантажені резидентні програми, поки не досягне "своєї"програми або не поверне управління в викликала програму через обробник
DOS (який, очевидно, завжди буде самим останнім у ланцюжку). P>
Природно, для комунікації з резидентної програмою повинен бутивстановлено певний інтерфейс. Зазвичай при перевірці на повторну установкурезидентна програма, якщо вона вже знаходиться в пам'яті, повертає врегістрі AL значення FFh, яке є ознакою заборони вторинноїзавантаження. Іноді для більшої надійності ідентифікації "своєї" функціїрезидентна програма, крім значення FFh в регістрі AL, повертає щеякісь обумовлені заздалегідь коди в інших регістрах. Часто черездодаткові регістри передасться символьна інформація, наприклад, ім'япрограми. У цьому випадку, якщо що викликала програма з ім'ям DUMP.COM (тобтодруга копія резидентної програми, яка з'ясовує, чи можна їй залишитисярезидентного в пам'яті) отримує після виклику int 2Fh в регістрі AL значення
FFh, а в регістрах СХ і DX символьні коди 'DU' і 'МР', вона може бутивпевнена, що її перша копія вже знаходиться в пам'яті. Якщо ж в регістрі ALповернувся код FFh, а в регістрах СХ і DX-коди, наприклад, 'ОК' і 'RB', це,швидше за все означає, що закріплена за нашою програмою функціямультиплексного переривання вусі використовується інший резидентну програму.
У цьому випадку варто змінити функцію, щоб не порушувати конфліктнихситуацій. p>
У резидентну частину варто включити обробник переривання 2Fh. Йогорозташування в межах тексту програми не має особливого значення, і мипомістили його на початку резидентної частини. Секція ініціалізації зазналавеликі зміни. Вона повинна починатися з виклику переривання 2Fh звідповідної функцій для перевірки на повторну установку. Якщо першакопія програми вже завантажена, поточну програму слід завершити нефункцією 3th (завершити і залишити в пам'яті), а звичайною функцією завершення
4Ch. Якщо ж нашої програми в пам'яті немає, то в секції ініціалізації,крім заповнення її "робочого" вектора, в даному випадку 03h, слід такожвстановити наш обробник мультиплексного переривання. p>
Серед функцій мультиплексного переривання, призначених для прикладнихпрограм, ми довільно вибрали для нашої програми функцію F1h, а дляперевірки на повторну установку підфункції 00h. Резидентний обробникпереривання 2Fh, що входить в нашу програму, перевіряє номери функції іпідфункції і при виявленні будь-яких інших кодів передає управліннянаступного обробникові цього переривання. Якщо ж викликана функція F1h зпідфункції 00h, оброблювач встановлює в регістрі AL значення FFh ( "явже завантажений ") і повертає керування в викликала програму командою iret. p>
Секція ініціалізації починається з перевірки на повторну установку. Післязавантаження в регістр АН номера функції (F1h), а в регістр AL - номерипідфункції (00h), викликається переривання 2Fh. Після повернення з перериванняаналізується вміст регістру AL Якщо обробник повернув значення FFh,програма повинна завершитися без залишення в пам'яті. Ці діївиконуються по мітці installed. Якщо повернуто інше значення,ініціалізація продовжується (для надійності варто було перевірити, чи повернутосаме 0). Зберігається старе вміст вектора 2Fh, встановлюється нашобробник цього переривання, після чого виконуються всі дії поустановки, передбачені в попередньому варіанті програми динамічного дампа.
При переході на мітку installed на екран виводиться повідомлення пронеможливості повторної установки і виконується функція завершення 4Сh зкодом повернення 01h. Останнє, звичайно, має символічний характер,оскільки цей код надалі не аналізується. p>
2.3. Вивантаження резидентної програми з пам'яті p>
Слід зауважити, що в DOS відсутні кошти вивантаження резидентнихпрограм. Єдиний передбачений для цього механізм - перезавантаженнякомп'ютера. Практично, однак, більшість резидентнихпрограмних продуктів мають вбудовані засоби вивантаження. Зазвичай вивантаженнярезидентної програми здійснюється відповідною командою, яка подається зклавіатури і сприймається резидентну програму. Для цього резидентнапрограма повинна перехоплювати переривання, що надходять з клавіатури, і
"виловлювати" команди вивантаження. Інший, боже простий спосіб полягає взапуску деякої програми, яка за допомогою, наприклад, мультиплексногопереривання 2Fh передає резидентної програмі команду вивантаження. Найчастішев якості "вивантажуються" використовують саму резидентну програму, точніше, їїдругу копію, яка, якщо її запустити в певному режимі, не тількине намагається залишитися в пам'яті, але, навпаки, вивантажує з пам'яті своюпершу копію. p>
вивантаження резидентної програми з пам'яті можна здійснити різнимиспособами. Найпростіший - звільнити блоки пам'яті, які займаєпрограмою (власне програмою та її оточенням) за допомогою функції DOS
49h. Другий, більш складний - використовувати в вивантажуються програмі функціюзавершення 4Ch, змусивши її завершити не саму вивантажують, а резидентнупрограму, та ще й після цього повернути управління в вивантажують. У будь-якомувипадку перед звільненням пам'яті необхідно відновити всі векторипереривань, перехоплені резидентну програму. Слід підкреслити, щовідновлення векторів представляє в загальному випадку значну і інодінавіть нерозв'язну проблему. По-перше, старе вміст вектора, якезберігається десь у полях даних резидентної програми, неможливо витягнути
"зовні", з іншої програми, тому що немає ніяких способів визначити,де саме його сховала резидентна програма в процесі ініціалізації.
Тому вивантаження резидентної програми легше здійснити з неї самої, ніжз іншої програми. По-друге, навіть якщо вивантаженняу здійснює самарезидентна програма, вона може правильно відновити старе вміствектора лише в тому випадку, якщо цей вектор не був пізніше перехоплений іншийрезидентну програму. Якщо ж це сталося, в таблиці векторів знаходитьсявже адресу не вивантажується, а наступного резидентної програми, і якщовідновити старе вміст вектора, ця наступна програма "зависне",позбавивши засобів свого запуску. Тому надійно можна вивантажити тількиостанню із завантажених резидентних програм. p>
В нашій програмі підфункції 00h переривання 2Fh служить для перевірки наповторну установку, а підфункції 01h - для розвантаження. У секціюініціалізації додані рядки збереження старого вмісту вектора 09h.
Це виконується точно так само, як і для вектора 2Fh - за допомогою функції DOS
35h. Старий вектор зберігається в комірці old_09h, що розміщується в резидентноїчастини програми. Оскільки вивантаження програми виконується за допомогоюпереривання 2Fh, текст обробника цього переривання ускладнюється. p>
Резидентний обробник переривання 2Fh насамперед перевіряє номерфункції, що надійшов в регістрі АН, Якщо цей номер відрізняється від F1h,керування передається наступному обробникові по ланцюжку. Даліаналізується вміст регістру AL. Якщо AL = 00h, виконуються дії позахист від повторного завантаження. Якщо AL = 01h, здійснюється перехід на міткуuninstall для виконання дій з вивантаження програми. При будь-якому іншомуномері підфункції керування передається наступному обробникові по ланцюжку. p>
За мітці uninstall здійснюється збереження використовуваних далі регістрів
(що робиться швидше для краси, ніж за потребою) та функції DOS 25hвідновлюється з осередків old_09h і old_2Fh оригінал вміствідповідних векторів. Далі з комірки із зсувом 2Ch щодопочатку PSP в регістр ES завантажується адреса оточення програми. Сегментнийадреса вивільняється блоку пам'яті - єдиний параметр, необхідний длявиконання функції DOS 49h. Розмір вивільняється блоку DOS відомий, вінзберігається в блоці управління пам'яттю (МСВ). Далі звільняється блок пам'ятіз самою програмою. Сегментний адресу цього блоку (адреса PSP) знаходиться врегістрі CS. Нарешті, командою iret управління передасться в програму,що викликала переривання 2Fh. p>
Функція 49h DOS сповіщає про те, що даний блок пам'яті вільний і моженадалі використовуватись DOS. Це, однак, не заважає виконуватися завершальнимрядках програми (в даному випадку - команді iret), оскільки звільненняпам'яті не руйнує її вмісту. Наша резидентна програма фізичнозітреться лише після того, як в пам'ять буде завантажена черговавиконувана програма. p>
Якщо програма запускається з клавіатури із зазначенням будь-яких параметрів
(імен файлів, ключів, які визначають режим роботи програми та ін.), то DOS,завантаживши програму в пам'ять, поміщає всі символи, введені після іменіпрограми (так званий хвіст команди) префікс програмного сегментапрограми, починаючи з відносного адреси 80h. Хвіст команди поміщається в
PSP в цілком певному форматі. У байт за адресою 80h DOS заносять числосимволів у хвості команди (включаючи пробіл, що розділяє на командному рядкусаму команду і її хвіст). Далі (починаючи з байти за адресою 81h) дотримуються всісимволи, введені з клавіатури до натиснення клавіші. Завершуєтьсяхвіст колом повернення каретки (13). p>
До даних секції ініціалізації додалася рядок з очікуваним хвостомкоманди і байтовий прапор запиту на розвантаження. p>
Оскільки дії програми при її запуску залежать від того, введена чикоманда запуску з параметром чи ні, наявність хвоста в PSP аналізується всамому початку секції ініціалізації. При запуску програми типу СОМ всесегментні регістри вказують на початок PSP. Байт з довжиною хвоста
(можливо, нульовий) поміщається в регістр CL і порівнюється з нулем. Якщо вньому 0, команда запуску була введена без параметрів і ініціалізаціяпрограми продовжується звичайним чином. Якщо хвіст має ненульову довжину,починається його аналіз. p>
обнуленням регістра СН довжина хвоста "розширюється" на весь регістр СХ, щопотрібно для організації циклу. Регістр DI налаштовується на перший байтхвоста, а регістр SI - на початок поля tail з очікуваною формою параметра.
Регістр AL готується для виконання команди сканування рядка.
Команда scasb порівнює в циклі байти хвоста з вмістом AL (кодомпробілу). Порівняння ведеться до тих пір, поки не буде знайдений перший символ,відмінний від пропуску. Ця операція необхідна через те, що оператор привведенні команди вивантаження може відокремити параметр команди від самої командибудь-якою кількістю пропусків, які потраплять у хвіст команди в PSP і перешкодятьаналізувати введений параметр. p>
Вихід з циклу виконання команди scasb здійснюється, коли командапроаналізувала перший після пробілу символ. Після цього регістр DIвказує на другий символ параметра. Команда dec DI коригує покажчик
DI, спрямовуючи його на перший значущий символ введеного параметра. Далікомандою порівняння рядків cmpsb здійснюється порівняння трьох, що залишилисясимволів хвоста. Якщо символи збігаються з параметром 'off', записаним впрограмі, встановлюється прапор запиту на розвантаження. Якщо результатпорівняння виявився негативним, прапор запиту не встановлюється (і,отже, неправильний параметр просто не сприймається). У будь-якійвипадку здійснюється перехід на продовження програми, що починаєперевіряти, чи не встановлена чи вже ця програма в пам'яті. Якщо програма щене встановлена, введений параметр не має сенсу. Ініціалізаціяздійснюється звичайним чином: зберігаються і встановлюються вектори іпрограма завершується з залишенням в пам'яті. p>
При наявності в пам'яті резидентного копії цієї програми здійснюєтьсяперехід на мітку installed, де перш за все перевіряється, чи встановленийпрапор запиту на розвантаження. Якщо прапор скинутий, виводиться повідомлення пронеможливості повторної завантаження і програма завершується з кодом повернення
1. Якщо прапор запиту встановлено, виконується вивантаження програми, якаполягає у виклику мультиплексного переривання 2Fh з функцією F1h іпідфункції 01h. Резидентний обробник цього переривання, що входить вскладу нашої резидентної програми, відпрацює цю підфункції, відновитьвектори і звільнить зайняті програмою блоки пам'яті. Після поверненняуправління з обробника в поточну програму буде виведено повідомлення проуспішної вивантаження і програма буде завершена функцією 4Ch з нульовим кодомповернення. p>
Складена нами програма не позбавлена від недоліків. Так, у нійаналізуються завжди тільки 3 значущих символу хвоста. Таким чином,програма буде вивантажено і при введенні команди (ім'я). com onset. Іншийнедолік полягає в тому, що результат порівняння записаного впрограмі хвоста з введенням з клавіатури параметром буде позитивним,тільки якщо з клавіатури введені малі літери. Команда (ім'я) OFF НЕпризведе до вивантаження програми. По-справжньому слід було включити до програмиперед аналізом хвоста перетворення символів параметра в прописні букви. p>
2.4. Перехоплення переривань p>
В архітектурі процесорів 80х86 передбачені особливі випадки, колипроцесор припиняє (перебиває) виконання поточної програми і негайнопередає керування програмі-оброблювачеві, спеціально написаної дляобробки подібної ситуації. Такі особливі ситуації поділяються на дві тина:переривання і виключення, в залежності від того, чи викликало цю ситуаціюяке-небудь зовнішній пристрій або виконується процесором команда.
Винятки далі діляться на три типи: помилки, пастки і зупиниться, узалежно від того, коли по відношенню до викликала їх команди вонивідбуваються. Помилки з'являються перед виконанням команди, тому обробниктакого виключення отримає як адресу повернення адреса помилковоюкоманди (починаючи з процесорів 80286). Пастки відбуваються відразу післявиконання команди, так що обробник отримує як адресу поверненняадреса наступної команди. І нарешті, зупинитися можуть виникати в будь-який моменті взагалі не передбачати коштів повернення управління в програму. p>
Команда INT (а також INTO і INT3) використовується в програмах як раз длятого, щоб викликати обробники переривань (або виключень). Фактичновони є винятками пастки, оскільки адреса повернення, якийпередасться обробникові, вказує на наступну команду, але так як цікоманди були введені до поділу особливих ситуацій на переривання івинятку, їх практично завжди називають командами виклику переривань.
З огляду на те, що обробники переривань і виключень в DOS зазвичай нерозрізняють механізм виклику, за допомогою команди INT можна передаватиуправління, як на обробники переривань, так і винятків. Як показано вчолі 4, програмні переривання, тобто передача керування за допомогоюкоманди INT, є основним засобом виклику процедур DOS і BIOS, томущо на відміну від дзвінка через команду CALL тут не потрібно знати адресивикликається процедури - достатньо лише номери. З іншого бокуінтерфейсу розглянемо, як будується обробник програмного переривання. p>
2.5. Обробники переривань p>
Коли в реальному режимі виконується команда INT, управління передається поадресою, що зчитується із спеціального масиву, таблиці векторівпереривань, що починається в пам'яті за адресою 0000h: 0000h. Кожен елементтакого масиву являє собою далекий адреса обробника переривання вформаті сегмент: зсув або 4 нульових байтів, якщо обробник НЕвстановлений. Команда INT поміщає в стек регістр прапорів і дальній адресаповернення, тому, щоб завершити обробник, треба виконати команди popfі retf або одну команду iret, яка в реальному режимі повністю їманалогічна.
Після того як обробник написаний, наступний крок - прив'язка його дообраному номеру переривання. Це можна зробити, прямо записав його адресу втаблицю векторів переривань.
Хоча пряме зміна таблиці векторів переривань і здається доситьзручним, все-таки це не найкращий підхід до встановлення обробника переривання,і користуватися ним слід тільки у виняткових випадках, наприклад, усерединіобробників переривань. Для звичайних програм DOS надає двасистемні функції: 25h і 35h - встановити і вважати адреса обробникапереривання, які і рекомендуються до використання в звичайних умовах.
Зазвичай обробники переривань застосовують з метою обробки переривання відзовнішніх пристроїв або з метою обслуговування запитів інших програм. p>
2.6. Переривання від зовнішніх пристроїв p>
Переривання від зовнішніх пристроїв або апаратні переривання, - це те, щорозуміється під терміном «переривання». Зовнішні пристрої (клавіатура,дисковод, таймер, звукова карта і т. д.) подають сигнал, за якимпроцесор перериває виконання програми та передає управління наобробник переривання. Всього на персональних комп'ютерах використовується 15апаратних переривань, хоча теоретично можливості архітектури дозволяютьдовести їх кількість до 64.
- IRQ1 (INT 9) - переривання клавіатури, викликається при кожному натисканні і відпуску клавіші на клавіатурі. Стандартний оброблювач цього переривання виконує досить багато функцій, починаючи з перезавантаження по Ctrl-Alt-Del і закінчуючи приміщенням коду клавіші в буфер клавіатури BIOS.
Найкорисніші для програм апаратні переривання - переривання системноготаймера і клавіатури. Так як стандартні обробники цих перериваньвиконують безліч функцій, від яких залежить робота системи, їх не можназамінювати повністю.перерваної програмі. Цей спосіб застосовують, якщо потрібно, щоб спочаткувідпрацював новий обробник, а потім він передав управління старому
Резидентні програми, що перехоплюють апаратні переривання, маютьвластивістю виконуватися одночасно з будь-якою іншою програмою. Самедля цього і застосовується механізм апаратних переривань - вони дозволяютьпроцесору виконувати одну програму, у той час як окремі програмистежать за часом, зчитують символи з клавіатури і поміщають їх у буфер,отримують і передають дані через послідовні і паралельні порти інавіть забезпечують багатозадачність, перемикаючи процесор між різнимизавданнями по перериванню системного таймера.
Зрозуміло, обробка переривань не повинна займати багато часу: якщопереривання відбувається досить часто (наприклад, перериванняпослідовного порту може відбуватися 28 800 разів на секунду), йогообробник обов'язково повинен виконуватися за більш короткий час. Якщо,наприклад, обробник переривання таймера буде виконуватися 1/32, 4 секунди,тобто половину часу між переривань, вся система стане працювати вдва рази повільніше. А якщо ще одна програма з таким же довгимобробником перехопить це переривання, система зупиниться зовсім. Саметому обробники переривань прийнято писати виключно на асемблері. p>
2.7. Резидентний обробник переривань від клавіатури з підключенням до системного обробника p>
Практично будь-яка програма, в якій передбачено управління ходом їївиконання за допомогою команд, що подаються з клавіатури, має у своєму складіобробник переривань від клавіатури. В залежності від поставлених перед нимзавдань, обробник може підключатися до системного, виконуючи обробку скан -кодів натискає клавішу, або після системною, працюючи в цьому випадку зкодами ASCII. що виникають на виході системного обробника. Нерідківипадки, коли прикладної обробник виконує частину своїх функцій досистемного, а частина - після. Ця й кілька наступних статейприсвячені цієї важливої для прикладного програміста питання. p>
Для того щоб написати, обробник переривань від клавіатури, необхіднодобре уявляти, яким чином вводяться, куди потрапляють і якобробляються символи, що вводяться з клавіатури. Процес взаємодіїсистеми з клавіатурою показано на рис. 2.3. P>
IRQ INT p>
Адреса системного p>
Апаратне Контролер Мікро -обробника int09h переривання переривань Вектор09 процесор з вектора
09 на IRQ1 p>
IRQ7 Запуск систем p>
Натискання або обробника int09h p>
відпускання Байт прапорів будь-якої клавіші Системнийклавіатури p>
Контролер Порт 60h обробник
[40h: 17h] клавіатури скан-код int09h | 7 | 6 | 5 | 4 |
3 | 2 | 1 | 0 | p>
Клавіатура p>
Ins p>
скан-код Код Caps Lock p>
Кільцевій буфер ASCII Num
Lock p>
40h: 1Eh введення Scroll Lock p>
40h: 1Ah p>
Alt p>
Адреса головного скан ASCII Ctrl символу скан ASCII Shift лівий
скан ASCII Shift правий p>
Програма скан ASCII користувача Адреса хвостового p>
(((символу p>
Вам не потрібно встановлювати 40h: 3Ch з клавіатури Введення самого p>
"старого" символу
Рис. 2.3. Процес взаємодії системи з клавіатурою. P>
Роботою клавіатури управляє спеціальна електронна схема - контролерклавіатури. У його функції входить розпізнавання натиснутою клавіші і приміщеннязакріпленого за нею коду у свій вихідний регістр (порт) з номером 60h. Кодклавіші, що надходить у порт, називається скан-кодом і є, по суті,порядковим номером кла -Віші. При цьому кожній клавіші присвоєні два скан-коду, що відрізняються один відодного на 80h. Один скан-код (менший, код натискання) засилається контролерому порт 60h при натисканні клавіші, інший (більший, код відпускання) - за їївідпуску. p>
скан-код однозначно вказує на натиснуту клавішу, однак, за нього не можнавизначити, чи працює користувач на нижньому або верхньому регістрі. Зіншого боку, скан-коди присвоєні всім клавішах клавіатури, в тому числікеруючим клавішах,,, та ін Такимчином, очевидно, що визначення введеного символу має містити всебе не тільки зчитування скан-коду натиснутою клавіші, але і з'ясування того,чи не були перед цим натиснуті, наприклад, клавіші (верхній регістр)або (фіксація верхнього регістру). Усім цим аналізом займаєтьсяпрограма обробки переривань від клавіатури. p>
Як натискання, так і відпускання будь-якої клавіші викликає сигнал апаратногопереривання, що змушує процесор перервати виконувану програму і перейтина програму системного обробника переривань від клавіатури, що входить досистему BIOS. Оскільки обробник викликається через вектор 09h, його інодіназивають програмою int09h. p>
Програма int09h, крім порту 60h, працює ще з двома областямиоперативної пам'яті: кільцевих буфером введення, розташовується за адресою від
40h: lEh до 40h: 3Dh, куди зрештою містяться коди ASCII натиснутихклавіш, і бітом прапорів клавіатури, що знаходиться за адресою 40h: 17h, дефіксується стан керуючих клавіш (,, та ін.) p>
Програма int09h, отримавши управління в результаті переривання відклавіатури, зчитує з порту 60h скан-код і аналізує його значення.
Якщо скан-код належить одній з керуючих клавіш, і, до того ж,представля?? т собою код натискання, в байті прапорів клавіатури встановлюєтьсябіт (прапор), що відповідає самій клавіші. Наприклад, якщо натиснути правоюклавіші в байті прапорів встановлюється біт 0, при натисканні лівоїклавіші - біт 1, при натисканні будь-якої клавіші - біт 2 і т.д.
Бити прапорів зберігають свій стан, поки клавіші (поодинці або в будь-якихкомбінаціях) залишаються натиснутими. Якщо управляюча клавіша відпускається,програма int09h отримує скан-код відпускання і скидає відповіднийбіт в байті прапорів. Крім стану зазначених клавіш, в байті прапорівфіксуються ще режими,, і
(див. рис. 2.3). p>
Комп'ютери PC/AT мають другий байт прапорів клавіатури, що знаходиться заадресою 40h: 18h, і відображає стан керуючих клавіш на розширеній
(101-клавішною) клавіатурі. P>
При натисканні звичайної, не керуючої клавіші, програма int09h зчитуєз порту 60h її скан-код натискання і по таблиці трансляції скан-кодів в коди
ASCII формує багатобайтових код, старший байт якого містить скан-код,а молодший код ASCII. При цьому якщо скан-код характеризує клавішу, то код
ASCII визначає закріплений за нею символ.
Оскільки за кожною клавішею закріплено, як правило, не менше двохсимволів ( "а" і "А", "1" і "!", "2" і "@" і т.д.), то кожному скан-кодувідповідають, як мінімум, два коди ASCII. У процесі трансляції програмаint09h аналізує стан прапорів, так що якщо натиснута, наприклад, клавіша
Q (скан-код 10h, код ASCII букви Q - 51h, а букви q - 7lh), то формуєтьсябагатобайтових код 1071h, але якщо клавіша натиснута Q, утримуючи клавішу
(зміна регістру), то результат трансляції складе 1051h. Той жекод 1051h вийде, якщо при натисканні клавіші Q був включений режим (великі літери), однак при включеному режимі і тій самійклавіші утворюється код 1071h, оскільки в такій ситуації клавіша на час натиснення переводить клавіатуру в режим нижнього регістрі
(малі літери). p>
Отриманий в результаті трансляції багатобайтових код засилається програмоюint09h в кільцевий буфер введення, який служить для синхронізації процесіввведення даних з клавіатури і прийому їх виконуваної комп'ютером програмою.
Обсяг буфера складає 16 слів, при цьому коди символів витягуються з ньогов тому ж порядку, в якому вони в нього надходили. За станом буфера стежатьдва покажчика. У хвостовому покажчику (слово за адресою 40: lCh) зберігаєтьсяадреса перші банківські сейфи, в головному покажчику (40: 1Ah) - адресасамого старого коду, прийнятого з клавіатури і ще не затребуваногопрограмою. Обидва адреси представляють собою зміщення відносно початкуобласті даних BIOS, тобто числа від 1Eh до 3Ch. На початку роботи, коли буферпорожній, обидва покажчика - і хвостовій, і головний, вказують на першу коміркубуфера. p>
Програма int09h, сформувавши багатобайтових код, поміщає його в буфер поадресою, яка передається в хвостовому покажчику, після чого ця адресазбільшується на 2, вказуючи знову на першу вільну комірку. Кожнеподальше натиснення на будь-яку клавішу додає в буфер черговийбагатобайтових код і зміщує хвостовій покажчик. p>
Виконувана програма, бажаючи отримати код натиснутою клавіші, повиннаобрати