Результат работы.
# gcc int6.c -o int6
# ./int6
01/13/10
19:16:19
01/13/10
4. Прерывания в DOS
Целью работы является приобретение знаний о типах внутренних прерываний и флаговой логики процессора, об источниках возникновения внутренних прерываний. Также приобретаются навыки использования механизма внутренних прерываний при решении практических задач (приемы перехвата прерываний и передачи управления соответствующим системным обработчикам).
Необходимо проанализировать содержимое стандартного обработчика прерывания по ошибке операции деления, то есть проверить, как реагирует операционная система на переполнение при выполнении команды деления.
Прерывание int 0 (деление на ноль) – внутреннее прерывание, вырабатываемое процессором.
Текст программы:
Результат выполнения:
Divide overflow
В результате выполнения программы было получено сообщение об ошибке.
Следует заменить стандартный обработчик int 0 на собственный, используя функции DOS для замены вектора прерывания и функцию 9h прерывания int 021h (функция dos 9) для иллюстрации работы обработчика. Алгоритм приведён на рис.
Рис. Алгоритм обработки исключения прерывания int 0
print macro
push ax, dx
lea dx, #1
mov ah, 9
int 021
pop dx, ax
#em
jmp start
_msg db '? Division by zero_new', 13, 10, '$'
n_vect equ 0
old_v dd ?
start:
mov ax, 035 by n_vect ; Сохранение вектора
int 021 ; es:bx
mov word ptr old_v, bx
mov w old_v + 2, es
mov ax, 025 by n_vect ; Установка нового вектора
lea dx, new ; ds:dx
int 021
mov ax, 100 ; Деление на 0
mov bl, 0
div bl
l1: push ds ; Восстановление прежнего вектора
mov ax, 025 by n_vect
mov dx, w old_v
mov ds, w old_v + 2
int 021
pop ds
int 020
new: ; Обработчик прерывания
print _msg
pop ax
mov ax, l1
push ax
iret
Результат выполнения:
Division by zero_new
В программе заменяется стандартный обработчик прерывания int 0 на собственный. По окончании обработки прерывания происходит восстановление прежнего вектора.
При возникновении прерывания в стек заносятся последовательно флаги, CS и IP (Instruction Pointer). IP указывает на расположение команды, вызвавшей прерывание. В нашем обработчике происходит извлечение из стека этого значения и занесение в аккумулятор адреса следующей выполняемой команды (метка l1). Соответственно в стек помещается новый адрес возврата.
Замена программных прерываний
Преобразуем программу так, чтобы не применять функции DOS для получения и установки вектора прерываний int 0.
print macro
push ax, dx
lea dx, #1
mov ah, 9
int 021
pop dx, ax
#em
jmp start
_msg db '? Division by zero_new', 13, 10, '$'
n_vect equ 0
old_v dd ?
start:
lea ax, new ; Установка нового вектора прерывания
mov dx, cs ; Сохранение старого
mov es, 0
es xchg w [n_vect * 4], ax
es xchg w [n_vect * 4 + 2], dx
mov w old_v, ax
mov w old_v + 2, dx
mov ax, 100
mov cl, 0
div cl
push ds ; Восстановление прежнего вектора прерывания
mov ax, w old_v
mov dx, w old_v + 2
es mov w [n_vect * 4], ax
es mov w [n_vect * 4 + 2], dx
pop ds
int 020
new:
print _msg
pop ax
add ax, 2
push ax
iret
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.