Управление процессами и нитями, страница 7

Результат работы.

# gcc int6.c -o int6

# ./int6

01/13/10

19:16:19

01/13/10

4. Прерывания в DOS

Целью работы является приобретение знаний о типах внутренних прерываний и флаговой логики процессора, об источниках возникновения внутренних прерываний. Также приобретаются навыки использования механизма внутренних прерываний при решении практических задач (приемы перехвата прерываний и передачи управления соответствующим системным обработчикам).

    Анализ содержимого стандартного обработчика прерывания при делении на ноль

Необходимо проанализировать содержимое стандартного обработчика прерывания по ошибке операции деления, то есть проверить, как реагирует операционная система на переполнение при выполнении команды деления.

Прерывание int 0 (деление на ноль) – внутреннее прерывание, вырабатываемое процессором.

Текст программы:

mov   ax, 100

mov   bl, 0

div   bl

Результат выполнения:

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