前面的中断处理程序过于简单了,只有一句iretd,而且这个时钟中断处理程序也只能发生一次,因为没有通知8259A本次中断处理程序已结束。就算处理程序能反复执行,我们也不能看到结果,所以还要在中断处理程序中添加一点显示信息来使我们知道中断程序在运行,下面就来修改:
HW_Int_00:
;push 0;
;call IRQ_Handler
;add esp,4
;hlt
mov al,20h
out 20h,al
inc byte [gs:0]
iretd
最好每前进一步就make一下,以便发现错误能及早发现,下面是结果:
可以看到左上角的字符按照ASCII码的顺序在跳动,这时显示的是感叹号。
由于在以后的时钟中断处理程序中我们想处理更多的问题,如进程调度等。那就免不了要使用寄存器了,那么在使用之前就必须把当前的寄存器的值保存到当前进程的PCB中,所以在中断程序刚刚开始的地方需要把各寄存器的值保存在当前的PCB中,由于TSS中的esp0字段刚好指向当前进程PCB的寄存器组的最高位置,所以使用就可以直接进行压栈操作了,在中断处理程序将要结束时就把PCB中的值再pop出去,下面修改一下代码:
HW_Int_00:
;push 0;
;call IRQ_Handler
;add esp,4
;hlt
pushad
push ds
push es
push fs
push gs
mov al,20h
out 20h,al
inc byte [gs:0]
pop gs
pop fs
pop es
pop ds
popad
iretd
如果是修改TSS中esp0的问题,如果我们有多个进程,需要在时钟中断处理程序中切换时,我们需要在中断处理程序中把esp0切到想要切换的那个进程的PCB的寄存器组的最高位置。现在的程序中只有一个进程在运行,所以这样做暂时是做无用功,那以后我们还是要实现多进程的,所以先这样做吧,免得以后忘记了,下面是修改:
HW_Int_00:
;push 0;
;call IRQ_Handler
;add esp,4
;hlt
pushad
push ds
push es
push fs
push gs
mov al,20h
out 20h,al
inc byte [gs:0]
lea eax,[esp + 68]
mov dword [tss + 4],eax
pop gs
pop fs
pop es
pop ds
popad
iretd
还有一个重要的问题,就是在时钟中断处理程序中免不了要使用堆栈,而经过一番push之后esp指向的是当前进程PCB的寄存器组的最低位置,如果此时在中断处理程序中调用一个函数的话,就会殃及到上一个进程的PCB,造成混乱。所以我们必须把堆栈切换到内核堆栈,而在中断处理程序将返回时把esp0又重新切换到当前进程的PCB的寄存器组的最高位置处,还得把ds,es切换回在GDT下的描述符,下面就来修改:
HW_Int_00:
;push 0;
;call IRQ_Handler
;add esp,4
;hlt
pushad
push ds
push es
push fs
push gs
mov dx,ss
mov ds,dx
mov es,dx
mov esp,Top_Of_Stack
mov al,20h
out 20h,al
inc byte [gs:0]
mov esp,[p_Resume_PCB]
lea eax,[esp + 68]
mov dword [tss + 4],eax
pop gs
pop fs
pop es
pop ds
popad
iretd
这样,我们的时钟中断处理程序稍微完善了一点,可以在中断程序中做我们想做的事情,如可以自由的调用一些函数而无需担心堆栈引起的问题,下面我们想在中断的过程中打印一些字符,下面来修改一下:
extern Disp_Color_Str
...
[section .data]
Int_Msg: db '*',0
...
HW_Int_00:
;push 0;
;call IRQ_Handler
;add esp,4
;hlt
pushad
push ds
push es
push fs
push gs
mov dx,ss
mov ds,dx
mov es,dx
mov esp,Top_Of_Stack
mov al,20h
out 20h,al
inc byte [gs:0]
mov eax,0dh
push eax
push Int_Msg
add esp,8
mov esp,[p_Resume_PCB]
lea eax,[esp + 68]
mov dword [tss + 4],eax
pop gs
pop fs
pop es
pop ds
popad
iretd
编译链接,在VPC下的运行结果如图所示:
在BOCHS下的运行结果如下:
可见,两个虚拟机的速度有明显的差距啊。。