
- •Передмова
- •Intel 430lx
- •Intel 430nx
- •Intel 430fx
- •Intel 430hx
- •Intel 430vx
- •Intel 430tx
- •Intel 450gx/kx
- •Intel 440fx
- •Intel 440lx agPset
- •Intel 440ex
- •Intel 440bx agPset
- •Заняття 1. Поняття про систему переривання пеом
- •Принципи організації системи переривання програм
- •Слово стану процесора (програми)
- •Характеристики системи переривання
- •Організація переходу до перериваючої програми та пріоритетне обслуговування запитів переривання
- •Процедура переривання з опитуванням джерел (прапорців) переривання
- •Програмно-керований пріоритет перериваючих програм
- •Методи використання механізму переривань
- •Класи переривань пеом
- •Призначення контролера апаратних переривань пеом
- •Опис основних елементів і8259а
- •Стани програмованого контролера переривань
- •Заняття 5. Керування режимами роботи пкп
- •Void main (void){
- •Int mask;
- •Заняття 6. Керування пріоритетами переривань
- •Install proc near
- •Заняття 8. Особливості практичного використання апаратних та програмних переривань
- •Volatile long ticks;
- •Void main(void) {
- •Void _interrupt _far timer(void) {
- •Int8 proc near cli
- •Int09 proc near
- •Розділ 3. Підсистема таймера та годинника реального часу
- •Заняття 3. Системні засоби програмного доступу до ресурсів таймера
- •Void tm_delay(int ticks) {
- •Void main (void){
- •Void main(void){
- •Заняття 4. Приклади використання функціональних можливостей таймера в прикладних задачах
- •Void main(void){ int Frac; char k;
- •Void tm_sound(int freq, int time) {
- •Void tm_delay(int ticks) {
- •Void tm_sound(int freq, int time){
- •Void main(){
- •Void main() { int I,j; clrscr();
- •Заняття 5. Архітектура та принципи функціонування годинника реального часу
Заняття 8. Особливості практичного використання апаратних та програмних переривань
Тема заняття
Вимоги до розробки оброблювачів переривання програм.
Мета заняття
Зрозуміти та засвоїти відмінності в розробці резидентних та нерезидентних оброблювачів переривання.
Навчитись коректно змінювати таблицю векторів переривання.
Вивчити методи використання свопінгу в резидентних програмах.
Засвоїти спосіб визначення "безпечного" моменту часу для використання дисків при свопінгу.
Написання власного оброблювача переривання
Існує кілька причин для написання власного переривання. Наприклад, багато Ваших програм можуть використовувати процедуру, що формує на екрані дисплея вертикальні рядки символів. Замість того, щоб включати її в кожну програму в якості процедури, Ви можете встановити її як переривання, написавши програму, яка стане резидентною в пам'яті та буде викликатися за необхідністю різними програмами.
Якщо Ваш програмний комплекс повинен працювати в реальному часі, відстежуючи деякі події, Вам не обійтись без використання якого-небудь окремого апаратного переривання, в якості зміни вектора переривання для замі-нення стандартного оброблювача своїм.
Часто виникає необхідність написання переривань, які повністю замінюють або модифікують ту чи іншу процедуру операційної системи, пристосовуючи її до умов конкретних програм користувача.
Зміна таблиці векторів переривань
Вашій програмі може знадобитись організувати обробку деяких переривань. Для цього програма повинна пере назначити вектор на свій оброблювач. Це можна зробити, змінивши вміст відповідного елемента таблиці векторів переривань. Дуже важливо не забути перед завершенням роботи відновити вміст змінених векторів у таблиці переривань, так як після завершення роботи програми пам'ять, яка була їй розподілена, вважається вільною та може бути використана для завантаження іншої програми. Якщо ви забули відновити вектор і прийшло переривання, то система може зруйнуватись, так як вектор тепер вказує на область, яка може містити що завгодно.
Тому послідовність дій для нерезидентних програм, що бажають обробляти переривання, повинна бути такою:
прочитати вміст елемента таблиці векторів переривань для вектора з потрібним Вам номером;
запам'ятати цей вміст (адреса старого оброблювача переривання) в області даних програми;
встановити нову адресу в таблиці векторів переривань так, щоб вона відповідала початку Вашої програми обробки переривання;
перед завершенням роботи програми прочитати з області даних адресу старого оброблювача переривання та записати його в таблицю векторів переривань.
Крім цього, операція зміни вектора переривання повинна бути безперервною в тому розумінні, що під час зміни не повинно відбутися переривання з номером, для якого здійснюється заміна програми обробки. Якщо Ви, наприклад, запишете нове значення зміщення, а сегментну адресу поновити не встигнете, то за якою адресою буде передано керування у випадку переривання і що при цьому відбудеться? Про це можна тільки здогадуватись.
Для полегшення роботи після заміни переривання DOS надає у Ваше розпорядження спеціальні функції для читання елемента таблиці векторів переривання та для запису в неї нової адреси. Якщо Ви будете використовувати ці функції, DOS гарантує, що операція після заміни вектора буде виконана правильно. Вам не потрібно турбуватись про безперервність процесу заміни вектора переривання.
Для читання вектора використовуйте функцію 35h переривання 21h- Перед її викликом регістр AL повинен містити номер вектора в таблиці. Після виконання функції в регістрах ES:BX буде шукана адреса оброблювача переривання.
Функція 25h переривання 21h встановлює для вектора з номером, що знаходиться в AL, оброблювач переривання DS:DX.
Звичайно, Ви можете безпосередньо звертатись до таблиці векторів переривань, але тоді під час запису необхідно замаскувати переривання командою CLI, не забувши дозволити їх після запису командою STI.
Для користувачів мови Сі бібліотека Quick C містить функції _dos_getvec(), _dos_setvect(). Перша функція отримує адресу з таблиці векторів переривань, друга встановлює нову адресу.
Якщо Вам треба додати які-небудь власні дії до тих, що виконує стандартний оброблювач переривання, то можна організувати ланцюг переривань.
Для організації ланцюга переривань Ви записуватимете у векторну таблицю адресу свого оброблювача, не забувши зберегти попередній вміст таблиці. Ваш оброблювач отримує керування по перериванню, виконує будь-які дії, далі передає керування стандартному оброблювачеві.
Можна зробити це інакше: Ваш оброблювач викликає стандартний як підпрограму, після повернення зі стандартного оброблювача виконує додаткові дії, тобто Ви можете вставити додаткову обробку як до виклику стандартного оброблювача, так і після його виклику.
У бібліотеці Quick C є функція для організації ланцюга переривань _chain_intr().
Розглянемо детальніше можливості бібліотеки інтегрованого середовища Quick C, призначеного для роботи з перериваннями.
Модифікатор interrupt (_interrupt для Quick C 2.5 та С 6.0) описує функцію, яка є оброблювачем переривання. Така функція завершується командою повернення з обробки переривання IRET, та для неї автоматично генеруються команди збереження регістрів на вході та їх відновлення при виході з оброблювача переривання. Приклад використання модифікатора для опису функції обробки переривання: void interrupt far int_funct(void) {
// Тіло оброблювача переривання
Функція обробки переривання повинна бути FAR функцією, так як таблиця векторів переривання містить повні адреси у вигляді сегмент: зміщення.
Ключове слово interrupt використовується також для опису змінних, що призначені для зберігання векторів переривань: void (_interrupt _far *oldvect)(void); Модифікатори _interrupt та _far для Quick C 2.5 та С 6.0 є синонімами відповідно interrupt та far.
Які вимоги висувають до програми обробки переривання?
Якщо переривання здійснюються часто, то їх обробка може сильно уповільнити роботу прикладної програми. Тому оброблювач переривання повинен бути короткою швидко працюючою програмою !!!, яка виконує тільки найнеобхідніші дії. Наприклад, зчитати черговий символ з порту принтера та помістити його в буфер, збільшити значення якого-небудь глобального лічильника переривань.
Для встановлення свого оброблювача переривань використовуйте функцію _dos_setvec. Ця функція має два параметри: номер переривання та покажчик на нову функцію обробки переривання.
Наприклад: dos_setvect(0xl6, my_key_intr);.
У цьому прикладі для клавіатурного переривання з номером 16h встановлюється новий оброблювач переривання my_key_intr.
Якщо Вам потрібно взнати адресу старого оброблювача переривання за його номером, найкраще скористатися функцією _dos_getvect, яка приймає в якості параметра номер переривання та повертає покажчик на оброблювач відповідний цьому номеру в таблиці векторів переривань. Наприклад: old_vector = _dos_getvect(0xl6); .
Для організації ланцюга переривань використовуйте функцію _cha in_intr. В якості параметра ця функція приймає адресу старого оброблювача переривань.
Наступний простий приклад ілюструє застосування всіх трьох функцій, призначених для роботи з перериваннями.
Ця програма встановлює власний оброблювач переривання таймера, який буде викликатись приблизно 18,2 рази за секунду. Цей оброблювач переривання рахує тіки таймера, і якщо значення лічильника кратне 20, на динамік комп'ютера видається звуковий сигнал. У кінці роботи нова програма обробки переривання таймера викликає старий оброблювач за допомогою _chain_intr.
Після встановлення нового оброблювача переривання таймера основна програма чекає натискання будь-яких клавіш клавіатури, далі вона відновлює старий вміст вектора переривання. #include <dos.h> #include <stdio.h>
#include <stdlib.h> //Вимикаємо перевірку стека
#pragma check_stack( off ) //та покажчиків #pragma check_pointer ( off )
//Це макро використовується для видачі сигналу //на внутрішній динамік комп'ютера. Використовується //вивід у форматі TTY символу BELL (7) через //переривання BIOS 10h #define BEEPO _asm { \
_asm mov bx,0 \
_asm mov ax, 0E07h \
_asm int lOh \
}
void main(void);
//Оголошення програми обробки переривання void _interrupt _far timer(void);
//Ця змінна призначена для зберігання старого //значення вектора переривання таймера. Вона //повинна бути глобальною void (_interrupt _far *oldvect)(void);
//Змінна для підрахунку тіків таймера