Обработка прерываний в реальном режиме производится в три этапа:
1) прекращается выполнение текущей программы;
2) запоминаются в стек FL, затем CS и IP, очищается флаг IF и осуществляется передача управления по адресу из таблицы векторов прерываний;
3) выполняется процедура обработки прерываний, и с помощью команды IRET возвращается управление прерванной программе. Команда IRET восстанавливает содержимое регистров IP, CS и FL.
Команда int n производит следующие действия:
push FL;
push CS;
push IP;
очищает бит IF;
передает в IP содержимое слова, имеющего адрес 4n;
передает в CS содержимое слова, имеющего адрес 4n+2.
Команда into генерирует прерывание 4, если флаг OF=1, в противном случае никаких действий не выполняет.
Собственные процедуры обработки прерываний.
Процедура обработки прерывания пишется как обычная подпрограмма, имеющая адрес, состоящий из четырех байт. В главной программе заполняется соответствующий вектор прерываний и вызывается процедура с помощью команды int.
Пример 1. Напишем программу, вызывающую собственную процедуру обработки прерывания, состоящую из единственной команды nop:
< 1 > title uintr
< 2 > code segment
< 3 > assume cs:code, ds:code
< 4 > vect equ 3fch
< 5 >
< 6 > main proc
< 7 > mov ax,0
< 8 > mov es,ax ;очистить es
< 9 > mov es:[vect+0], offset user
< 10 > mov es:[vect+2], cs
< 11 > int vect/4 ;вызов прерывания
< 12 > mov ah,0 ;ожидание
< 13 > int 16h
mov ax,4c00h
< 1 >
< 2 > int 21h
< 3 > main endp
< 4 >
< 5 > user proc far ;адрес из 4 байт
< 6 > nop
< 7 > iret
< 8 > user endp
< 9 > code ends
< 10 > end main
Более естественным является оставить собственную подпрограмму обработки прерывания резидентной. Такая подпрограмма называется драйвером. Это делается с помощью прерывания 27h.
Пример 2. Напишем подпрограмму обработки прерывания 1Ch, генерируемого при каждом тиканьи часов. Наша процедура будет выводить на экран после каждых 100 тиканий двоичное значение счетчика, заданного в регистре bx.
< 1 > title udriv.com
< 2 > code segment
< 3 > org 100h
< 4 > assume cs:code, ds:code, ss:code
< 5 > begin:
< 6 > jmp setdrv
< 7 > drv proc far
< 8 > push ax
< 9 > push bx
< 10 > push cx
< 11 > push dx
< 12 > push si
< 13 > push di
< 14 > push es
< 15 > push ds
< 16 > push cs
< 17 > pop ds
< 18 > mov ax,count
< 19 > inc ax
< 20 > mov count,ax
< 21 > cmp ax,10 ;если нет
< 22 > jb enddrv ;10 тиков
< 23 > mov ax,0
< 24 > mov count,ax
< 25 > mov bx,number
< 26 > inc bx
< 27 > mov number,bx
< 28 > mov ax,0b800h
< 29 > mov es,ax
< 30 > mov di,0 ;cs:[di] — начало экрана
< 31 > mov cx,16
< 32 > lp1:
< 33 > mov al,’0′
< 34 > shl bx,1
< 35 > jnc lp2
< 36 > inc al
< 37 > lp2:
< 38 > stosb ;al->es:[di]
< 39 > mov al,7 ;атрибут
< 40 > stosb
< 41 > loop lp1
< 42 > enddrv:
< 43 > pop ds
< 44 > pop es
< 45 > pop di
< 46 > pop si
< 47 > pop dx
< 48 > pop cx
< 49 > pop bx
< 50 > pop ax
iret
< 1 >
< 2 > count dw 0
< 3 > number dw 0
< 4 > finish equ $ ;отметка конца процедуры
< 5 > drv endp
< 6 > setdrv:
< 7 > mov dx,offset drv
< 8 > mov al,1Ch ;номер прерывания
< 9 > mov ah,25h ;функция установки вектора
< 10 > int 21h
< 11 > lea dx,finish ;оставить процедуру
< 12 > int 27h ;в памяти
< 13 > ret ;выход
< 14 > code ends
< 15 > end begin