中断处理程序是被动的,它只知道当忠实的中断发生时执行那段代码,完全不理会中断在何时发生。可是,为了避免这种嵌套现象的发生,我们必须想一个办法让中断处理程序知道 自己是不是在嵌套执行。
这个问题并不难解决,只要设置一个全局变量就可以了。这个全局变量有一个初值-1,当中断处理程序开始执行时它自加,结束时自减。在处理程序开头处这个变量需要被检查一下,如果值不是0 (0 =-1+1),则说明在一次中断未处理完之前就又发生了一 次中断,这时直接跳到最后,结束中断处理程序的执行。当然,武断地结束新的中断并不是一个好的办法,但在这里,我们姑且这 样来做。
ALIGN 16
hwint00: ; Interrupt routine for irq 0 (the clock).
sub esp, 4
pushad ; `.
push ds ; |
push es ; | 保存原寄存器值
push fs ; |
push gs ; /
mov dx, ss
mov ds, dx
mov es, dx
inc byte [gs:0] ; 改变屏幕第 0 行, 第 0 列的字符
mov al, EOI ; `. reenable
out INT_M_CTL, al ; / master 8259
inc dword [k_reenter]
cmp dword [k_reenter], 0
jne .re_enter
mov esp, StackTop ; 切到内核栈
sti
push clock_int_msg
call disp_str
add esp, 4
;;; push 1
;;; call delay
;;; add esp, 4
cli
mov esp, [p_proc_ready] ; 离开内核栈
lea eax, [esp + P_STACKTOP]
mov dword [tss + TSS3_S_SP0], eax
.re_enter: ; 如果(k_reenter != 0),会跳转到这里
dec dword [k_reenter]
pop gs ; `.
pop fs ; |
pop es ; | 恢复原寄存器值
pop ds ; |
popad ; /
add esp, 4
iretd