进程A在运行,时钟中断发生。
中断会读取TSS中ring0的esp。该esp指向进程A进程表的regs的最后,并且把进程A运行的cs,eip,ss,sp,eflags等信息压入到esp指向的进程表。
执行中断程序
执行中断程序最后一个iredt指令,因为现在esp指向进程表的cs,eip等参数,所以会把刚刚保存进进程表的进程A的参数压出到寄存器。
返回到进程A继续执行。
--------------------------------------------------------------------------
其实,即便我们打开了时钟中断,时钟中断也只会发生一次,因为我们没有将中断结束位EOI置为1,
告知8259A当前中断结束。当前中断结束,才可以开始下一个中断。
hwint00: ; Interrupt routine for irq 0 (the clock).
sub esp, 4 //中断会把cs,eip,eflags,ss,sp自动压入堆栈。跳过retAdrr成员
pushad ; `. //把所有e开头的寄存器压入堆栈
push ds ; |
push es ; | 保存原寄存器值
push fs ; |
push gs ; / //把ds,es,fs,gs寄存器的值压入堆栈
mov dx, ss
mov ds, dx
mov es, dx //使ss,ds,es的值相等。其实ss都是指kenel_ds,不同的是esp,不同的esp指向有可能是进程栈、内
核栈,进程表栈
mov esp, StackTop ; 切到内核栈
inc byte [gs:0] ; 改变屏幕第 0 行, 第 0 列的字符
mov al, EOI ; `. reenable
out INT_M_CTL, al ; / master 8259
push clock_int_msg
call disp_str
add esp, 4
mov esp, [p_proc_ready] ; 离开内核栈,到进程表栈
lea eax, [esp + P_STACKTOP] ;注意esp还是指向进程表堆栈头,esp+P_STACKTOP指向进程表的regs尾
mov dword [tss + TSS3_S_SP0], eax
pop gs ; `.
pop fs ; |
pop es ; | 恢复原寄存器值
pop ds ; |
popad ; /
add esp, 4
iretd