首先是把重复的代码合并掉,在初次进入进程之前的一系列pop等语句和时钟中断处理程序中的后半截的语句是雷同的,我们想把这些重复的代码合并在一起,先这样修改时钟中断处理系统:
HW_Int_00:
pushad
push ds
push es
push fs
push gs
mov dx,ss
mov ds,dx
mov es,dx
inc byte [gs:0]
mov al,20h
out 20h,al
inc dword [Is_Reenter]
cmp dword [Is_Reenter],0
jne .1
mov esp,Top_Of_Stack
push restart
jmp .2
.1:
push reenter
.2:
sti
mov eax,0dh
push eax
push Int_Msg
call Disp_Color_Str
add esp,8
call Clock_Handler
cli
ret
restart:
mov esp,[p_Resume_PCB]
lea dword eax,[esp + 68]
mov [tss + 4],eax
mov ax,[esp + 68]
lldt ax
reenter:
dec dword [Is_Reenter]
pop gs
pop fs
pop es
pop ds
popad
iretd
为什么要这样改啊?相信每个人刚开始看到这段代码都会很诧异,看到后面你就明白了。如果发生了重入,则压入.reenter标号,如果没有发生重入,则压入.restart标号,最后执行完Clock_Handler后一句ret就搞定了。我们的目的是什么,就是为了合并重复的代码咯,想达到某种目的,往往是要付出代价的。上面的修改不仅仅是修改了形式,内容上也有了少许变化,即使是中断重入了,也要调用Clock_Handler函数,我们来修改一下这个函数,让它在中断重入的时候打印一个感叹号后直接return,打印感叹号的目的是提醒我们此时发生中断重入:
- void Clock_Handler()
- {
- if(Is_Reenter != 0)
- {
- Disp_Color_Str("!",0xe);
- return;
- }
- p_Resume_PCB++;
- if(p_Resume_PCB >= PCB_Tables + 2)
- {
- p_Resume_PCB = PCB_Tables;
- }
- }
用到了Disp_Color_Str函数,需要包含proto.h头文件,MAKEFILE也别忘了加进来。
编译链接,结果不变。
接下来修改初次进入进程前的代码,我们要使这段代码跟时钟中断处理程序的后半段一样,直接复制过来就好,只是比原来多了一句:dec dword [Is_Reenter],为了保持一致,这就是代价,所以我们不得不改变Is_Reenter的初始值:
在global.c中:
- u32 Is_Reenter = 0;
那么初次进入进程前的代码变为:
_test:
;jmp 100:0
;sti
restart:
mov esp,[p_Resume_PCB]
lea dword eax,[esp + 68]
mov [tss + 4],eax
mov ax,[esp + 68]
lldt ax
reenter:
dec dword [Is_Reenter]
pop gs
pop fs
pop es
pop ds
popad
iretd
则时钟中断处理程序ret后面的代码就可以全部去掉了。
编译运行,结果不变,但我们的代码比起以前来更加简洁了。