一个操作系统的实现--中断门
作者:网络转载 发布时间:[ 2013/8/23 10:04:59 ] 推荐标签:
上图中除了两个Interrupt(中断)外,其他还有三种Fault、Trap、Abort异常。我们这里讨论的中断主要是用户定义中断,这种中断产生的原因有两种:一是外部中断,是由硬件产生的中断;另一种是由指令int n产生的中断。
通过指令int n产生中断的情形如第一张图所示,这有点像调用门的适用。
外部中断的情况则复杂一些,因为需要建立硬件中断和向量号之间的对应关系。外部中断的简单示意图如下:

通过对8259A的配置,可将IRQ0~IRQ7对应到中断向量20h~27h,同样地IRQ8~IRQ15可对应到中断向量28h~2Fh。具体初始化配置代码不进行分析了。
; IDT
[SECTION .idt] ;sect.idt #show#-->
ALIGN 32
[BITS 32]
LABEL_IDT:
; 门 目标选择子, 偏移, DCount, 属性
%rep 32
Gate SelectorCode32, SpuriousHandler, 0, DA_386IGate
%endrep
.020h: Gate SelectorCode32, ClockHandler, 0, DA_386IGate
%rep 95
Gate SelectorCode32, SpuriousHandler, 0, DA_386IGate
%endrep
.080h: Gate SelectorCode32, UserIntHandler, 0, DA_386IGate
IdtLen equ $ - LABEL_IDT
IdtPtr dw IdtLen - 1 ; 段界限
dd 0 ; 基地址
; END of [SECTION .idt]
[SECTION .s16]
[BITS 16]
LABEL_BEGIN:
; 为加载 IDTR 作准备
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_IDT ; eax <- idt 基地址
mov dword [IdtPtr + 2], eax ; [IdtPtr + 2] <- idt 基地址
; 保存 IDTR
sidt [_SavedIDTR]
; 保存中断屏蔽寄存器(IMREG)值
in al, 21h
mov [_SavedIMREG], al
; 加载 GDTR
lgdt [GdtPtr]
; 关中断
;cli
; 加载 IDTR
lidt [IdtPtr]
; 打开地址线A20
in al, 92h
or al, 00000010b
out 92h, al
; 准备切换到保护模式
mov eax, cr0
or eax, 1
mov cr0, eax
; 真正进入保护模式
jmp dword SelectorCode32:0 ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 Code32Selector:0 处
; Init8259A ---------------------------------------------------------------------------------------------
Init8259A:
mov al, 011h
out 020h, al ; 主8259, ICW1.
call io_delay
out 0A0h, al ; 从8259, ICW1.
call io_delay
mov al, 020h ; IRQ0 对应中断向量 0x20
out 021h, al ; 主8259, ICW2.
call io_delay
mov al, 028h ; IRQ8 对应中断向量 0x28
out 0A1h, al ; 从8259, ICW2.
call io_delay
mov al, 004h ; IR2 对应从8259
out 021h, al ; 主8259, ICW3.
call io_delay
mov al, 002h ; 对应主8259的 IR2
out 0A1h, al ; 从8259, ICW3.
call io_delay
mov al, 001h
out 021h, al ; 主8259, ICW4.
call io_delay
out 0A1h, al ; 从8259, ICW4.
call io_delay
;mov al, 11111111b ; 屏蔽主8259所有中断
mov al, 11111110b ; 仅仅开启定时器中断
out 021h, al ; 主8259, OCW1.
call io_delay
mov al, 11111111b ; 屏蔽从8259所有中断
out 0A1h, al ; 从8259, OCW1.
call io_delay
ret
; Init8259A ---------------------------------------------------------------------------------------------
LABEL_SEG_CODE32:
mov ax, SelectorData
mov ds, ax ; 数据段选择子
mov es, ax
mov ax, SelectorVideo
mov gs, ax ; 视频段选择子
mov ax, SelectorStack
mov ss, ax ; 堆栈段选择子
mov esp, TopOfStack
call Init8259A
int 080h
sti
jmp $
; int handler ---------------------------------------------------------------
_UserIntHandler:
UserIntHandler equ _UserIntHandler - $$
mov ah, 0Ch ; 0000: 黑底 1100: 红字
mov al, 'I'
mov [gs:((80 * 0 + 70) * 2)], ax ; 屏幕第 0 行, 第 70 列。
iretd

sales@spasvo.com