mov excep,7
int 32h
cmp cpu_type,2
jz @1
db 0ffh,2eh
dw ofs_ret_mov
@1:db 9ah
dw offset reset
dw code_sel2
end;
procedure exc_08;assembler; { Обработчик исключения 8: }
asm { двойная ошибка }
mov excep,8
int 32h
cmp cpu_type,2
jz @1
db 0ffh,2eh
dw ofs_ret_mov
@1:db 9ah
dw offset reset
dw code_sel2
end;
procedure exc_10;assembler; { Обработчик исключения 10: }
asm { недоступен TSS }
mov excep,10
int 32h
cmp cpu_type,2
jz @1
db 0ffh,2eh
dw ofs_ret_mov
@1:db 9ah
dw offset reset
dw code_sel2
end;
procedure exc_11;assembler; { Обработчик исключения 11: }
asm { недоступен сегмент }
mov excep,11
int 32h
cmp cpu_type,2
jz @1
db 0ffh,2eh
dw ofs_ret_mov
@1:db 9ah
dw offset reset
dw code_sel2
end;
procedure exc_12;assembler; { Обработчик исключения 12: }
asm { ошибка доступа к сегменту стека }
mov excep,12
int 32h
cmp cpu_type,2
jz @1
db 0ffh,2eh
dw ofs_ret_mov
@1:db 9ah
dw offset reset
dw code_sel2
end;
procedure exc_13;assembler; { Обработчик исключения 13: }
asm { нарушение общей защиты }
mov excep,13
int 32h
cmp cpu_type,2
jz @1
db 0ffh,2eh
dw ofs_ret_mov
@1:db 9ah
dw offset reset
dw code_sel2
end;
procedure exc_14;assembler; { Обработчик исключения 14: }
asm { недоступна страница }
mov excep,14
int 32h
cmp cpu_type,2
jz @1
db 0ffh,2eh
dw ofs_ret_mov
@1:db 9ah
dw offset reset
dw code_sel2
end;
procedure exc_16;assembler; { Обработчик исключения 16: }
asm { ошибка FPU при NE=1 регистра CR0 }
mov excep,16
int 32h
cmp cpu_type,2
jz @1
db 0ffh,2eh
dw ofs_ret_mov
@1:db 9ah
dw offset reset
dw code_sel2
end;
procedure exc_17;assembler; { Обработчик исключения 17: }
asm { ошибка выравнивания данных }
mov excep,17
int 32h
cmp cpu_type,2
jz @1
db 0ffh,2eh
dw ofs_ret_mov
@1:db 9ah
dw offset reset
dw code_sel2
end;
procedure exc_18;assembler; { Обработчик исключения 18: }
asm { ошибка функционирования узлов МП и МПС }
mov excep,18
cmp cpu_type,2
jz @1
db 0ffh,2eh
dw ofs_ret_mov
@1:db 9ah
dw offset reset
dw code_sel2
end;
{---------Обработчики-заглушки аппаратных прерываний,---------}
{----------поступающих на 1-й контроллер прерываний-----------}
procedure PIC_1;assembler;
asm
push ax
mov al,$20
out $20,al { Сброс бита регистра ISR 1-го ПКП }
pop ax
cmp cpu_type,2 { Если 80286 - разрядность 16, }
je @7 { иначе - 32 }
db 66h
@7:iret
end;
{---------Обработчики-заглушки аппаратных прерываний,---------}
{----------поступающих на 2-й контроллер прерываний-----------}
procedure PIC_2;assembler;
asm
push ax
mov al,$20 { Сброс бита регистра ISR }
out $20,al { 1-го и }
out $a0,al { и 2-го контроллеров прерываний }
pop ax
cmp cpu_type,2
je @8
db 66h
@8:iret
end;
procedure keyb;assembler; { Обработчик прерываний }
asm { от клавиатуры: }
mov al,20h
out 20h,al
in al,60h { Чтение скан-кода нажатия/отжатия клавиши }
test al,$80
jnz @k1 { Переход, если клавиша отжата }
mov scan,al
@k1:cmp cpu_type,2
je @k2
db 66h
@k2:iret
end;
procedure int_30h;assembler; { Обработчик программного }
asm { прерывания 30h: }
cmp ah,2 { AH - номер функции }
jz @i2 { Al - номер подфункции }
cmp ah,3 { BL - номер строки экрана }
jz @i3 { BH - номер столбца экрана }
cmp ah,4 { DL/DX/EDX - значение данных }
jz @i4 { (байта/слова/двойного слова) }
cmp ah,5 { CL - видео-атрибут }
jz @i5 { SI - смещение строки символов }
{ Функция 1: установка маркера в заданную точку экрана }
mov ax,bx
xor bh,bh
mov bl,ah
xor ah,ah
mov dl,80
mul dl
add ax,bx
shl ax,1
mov di,ax
jmp @end
@i2: { Функция 2: вывод символа на экран }
mov al,dl
mov ah,cl
stosw
jmp @end
@i3: { Функция 3: вывод данных на экран в 16-ричной форме }
{ AL=0 - вывод байта }
{ AL=1 -вывод слова }
{ AL=2 - вывод двойного слова }
lea bx,hex_tabl
mov ah,cl
cmp al,0
jz @8
cmp al,1
jz @16
add di,14
mov cx,8
jmp @1
@8:add di,2
mov cx,2
jmp @1
@16:add di,6
mov cx,4
@1:push cx
@lp:mov al,dl
and al,0fh
db 66h
shr dx,4
xlat
stosw
sub di,4
loop @lp
pop cx
shl cx,1
add cx,4 {2}
add di,cx
jmp @end
@i4: { Функция 4: вывод строки символов на экран }
mov ah,cl
mov bx,si
inc si
mov cl,[bx]
xor ch,ch
@wxy:
lodsb
stosw
loop @wxy
jmp @end
@i5: { Функция 5: вывод данных на экран в двоичной форме }
{ AL=0 - вывод байта }{ AL=1 -вывод слова }
{ AL=2 - вывод двойного слова }
{ lea bx,duo_tabl}
mov ah,cl
cmp al,0
jz @8_2
cmp al,1
jz @16_2
mov cx,8
jmp @2
@8_2:
mov cx,2
jmp @2
@16_2:
mov cx,4
@2:push cx
push cx
shl cx,3
sub cx,2
add di,cx { di+cx*8-2 }
pop cx
@lp_1:push cx
xor ah,8
mov cx,4
@lp_2:mov al,dl
and al,01h
db 66h
shr dx,1
xlat
stosw
sub di,4
loop @lp_2
pop cx
loop @lp_1
pop cx
shl cx,3
add cx,2 { di+cx*8+2 }
add di,cx
@end:db 66h
iret
end;
procedure int_30hr;assembler; { Обработчик программного }
asm { прерывания 30h: }
cmp ah,2 { AH - номер функции }
jz @i2 { Al - номер подфункции }
cmp ah,3 { BL - номер строки экрана }
jz @i3 { BH - номер столбца экрана }
cmp ah,4 { DL/DX/EDX - значение данных }
jz @i4 { (байта/слова/двойного слова) }
cmp ah,5 { CL - видео-атрибут }
jz @i5 { SI - смещение строки символов }
{ Функция 1: установка маркера в заданную точку экрана }
mov ax,bx
xor bh,bh
mov bl,ah
xor ah,ah
mov dl,80
mul dl
add ax,bx
shl ax,1
mov di,ax
jmp @end
@i2: { Функция 2: вывод символа на экран }
mov al,dl
mov ah,cl
stosw
jmp @end
@i3: { Функция 3: вывод данных на экран в 16-ричной форме }
{ AL=0 - вывод байта } { AL=1 -вывод слова }
{ AL=2 - вывод двойного слова }
lea bx,hex_tabl
mov ah,cl
cmp al,0
jz @8
cmp al,1
jz @16
add di,14
mov cx,8
jmp @1
@8:add di,2
mov cx,2
jmp @1
@16:add di,6
mov cx,4
@1:push cx
@lp:mov al,dl
and al,0fh
db 66h
shr dx,4
xlat
stosw
sub di,4
loop @lp
pop cx
shl cx,1
add cx,4 {2}
add di,cx
jmp @end
@i4: { Функция 4: вывод строки символов на экран }
mov ah,cl
mov bx,si
inc si
mov cl,[bx]
xor ch,ch
@wxy:
lodsb
stosw
loop @wxy
jmp @end
@i5: { Функция 5: вывод данных на экран в двоичной форме }
{ AL=0 - вывод байта }
{ AL=1 -вывод слова }
{ AL=2 - вывод двойного слова }
{ lea bx,duo_tabl}
mov ah,cl
cmp al,0
jz @8_2
cmp al,1
jz @16_2
mov cx,8
jmp @2
@8_2:
mov cx,2
jmp @2
@16_2:
mov cx,4
@2:push cx
push cx
shl cx,3
sub cx,2
add di,cx { di+cx*8-2 }
pop cx
@lp_1:push cx
xor ah,8
mov cx,4
@lp_2:mov al,dl
and al,01h
db 66h
shr dx,1
xlat
stosw
sub di,4
loop @lp_2
pop cx
loop @lp_1
pop cx
shl cx,3
add cx,2 { di+cx*8+2 }
add di,cx
@end: iret
end;
{------------------Вывод номера исключения--------------------}
procedure int_32h;assembler;
asm
mov ah,1 { Функция 1: установка маркера на экране }
mov bl,22 { с координатами - строка 22, }
mov bh,1 { столбец 1 }
int 30h
mov ah,4 { Функция 4: вывод на экран }
mov si, offset s2 { строки символов s2 }
mov cl,1ah { видеоатрибут }
int 30h
mov ax,300h { Функция 3, подфункция 0: }
mov dl,excep { вывод на экран номера исключения }
mov cl,1ch { видеоатрибут }
int 30h
db 66h
iret
end;
end.
(*16. а) Исключение, вызванное запретом чтения из сегмента кода б) Разработать обработчик прерывания от системного таймера, который каждые 5 секунд меняет цвет бордюра.
I. Вызвать требуемое в индивидуальном задании исключение.
II. Обработать это исключение одним из двух способов:
а) устранив причину исключения;
б) пропустив команду, вызвавшую исключение.
III. Обработать заданное внешнее прерывание.*)
program p_intr;
{ Обработка прерываний в защищенном режиме }
uses crt, prot; { Модуль PROT содержит константы, }
{ типы переменных, переменные, процедуры и функции }
{ для работы в защищенном режиме }
label ret_r; { Точка возврата в реальный режим }
const
s:string='Обработка исключений и прерываний в защищенном режиме';
s1:string='CS SS DS ES CR0 EFLAGS: ';
s2:string='Обработано исключение ';
s3:string='Na 5 tik timera menyaem cvet BORDURA.';
s4:string='Press Esc to exit';
var
cs_real, { Значение регистра CS в реальном режиме }
err, { Код ошибки }
lim1,lim2,count:word;
scan,i,al_,ah_,n_exc,row:byte;
sscan:byte;
eflags:longint;
quel,counter,color:byte;
dwd:word;
{--------------Разработка обработчиков исключений--------------}
procedure out_exc;assembler; { Вывод номера исключения }
asm
mov ah,1 { Функция 1: установка маркера на экране }
mov bl,22 { с координатами - строка 22, }
mov bh,1 { столбец 1 }
int 30h
mov ah,4 { Функция 4: вывод на экран }
mov si, offset s2 { строки символов s2 }
mov cl,1eh
int 30h
mov ax,300h { Функция 3, подфункция 0: }
mov dl,excep { вывод на экран номера исключения }
mov cl,1ch
int 30h
mov dx,dwd
ret
end;
procedure exc_00;assembler; { Обработчик исключения 0 }
{-----Два варианта устранения зацикливания обработки отказа----}
mov bl,1 { Вариант 1: устранение причины отказа }
pusha
(* push bp { Вариант 2: изменение в стеке значения }
mov bp,sp { счетчика команд IP на величину длины команды }
inc word ptr [bp+2]
pop bp *)
mov excep,0
call out_exc; { Вывод сообщения об обработке исключения }
popa
cmp cpu_type,2
jz @2
db 66h
@2:iret
end;
procedure exc_13;assembler; { Обработчик исключения 0 }
{-----Два варианта устранения зацикливания обработки отказа----}
asm
cmp cpu_type,2
jz @1
db 66h
@1:pop bx
{-------------Вариант 2: изменяет в стеке значение------------}
{-------------счетчика команд IP на длину команды,------------}
{-----------вызвавшей исключение (div bl - 1 байт)------------}
push bp
mov bp,sp
add word ptr [bp+2],4 { или inc word ptr [bp+2] }
pop bp
{---------------------Вывод сообщения-------------------------}
{---------о возникновении исключения с номером excep----------}
pusha
mov excep,13
int 32h
(*push bx
mov ax,501h { Функция 5: вывод на экран }
mov cl,1eh { кода ошибки в двоичной форме }
pop dx
int 30h *)
popa
{-------Вариант 3: выполняет выход из защищенного режима-------}
{----через межсегментный косвенный переход на метку ret_mov----}
(* db 0ffh,2eh
dw ofs_ret_mov *)
cmp cpu_type,2
jz @2
db 66h
@2:iret
end;
procedure exc_0b;assembler; { Обработчик исключения 11 }
{ вызывается при отсутствии сегмента в памяти и выполняет }
{ коррекцию дескриптора сегмента - востанавливает бит P }
asm
mov excep,0bh
cmp cpu_type,2
jz @1
db 66h
@1:pop bx { Чтение из стека кода ошибки }
mov err,bx { и запись в переменную err }
and bx,not 7 { Выделение смещения селектора }
add bx,offset gdt+5 { Выбор поля байта доступа в GDT }
push ax
mov al, [bx] { Чтение байта доступа сегмента }
or al,80h
mov [bx],al { Установка бита P=1 в байте доступа }
pop ax
cmp cpu_type,2
jz @2
db 66h
@2:iret
end;
procedure keyb;assembler; { Обработчик прерываний }
asm { от клавиатуры: }
mov al,20h
out 20h,al { Сброс контроллера прерываний }
in al,60h { Чтение скан-кода нажатия/отжатия клавиши }
test al,80h
jnz @1 { Переход, если клавиша отжата }
mov scan,al
@1:cmp cpu_type,2
jz @3
db 66h
@3:iret
end;
procedure ttim;assembler; { Обработчик прерываний }
asm { от timer: }
push ax
mov al,$20
out $20,al { Сброс бита регистра ISR 1-го ПКП }
pop ax
inc counter
cmp counter,5
jnz @99
mov counter,0
push dx
push ax
mov dx,3dah
in al,dx
mov dx,3c0h
mov al,11h
out dx,al
inc color
mov al,color