sconst.inc proc.h
P_STACKBASE equ 0 typedef struct s_stackframe{
GSREG equ P_STACKBASE u32 gs
FSREG equ GSREG + 4 u32 fs
ESREG equ FSREG + 4 u32 es
DSREG equ ESREG + 4 //pop gs...ds u32 ds
---------------------------------------------------------------------
EDIREG equ DSREG +4
ESIREG equ EDIREG + 4
EBPREG equ ESIREG + 4
KERNELESPREG equ EBPREG + 4
EBXREG equ KERNELESPREG + 4
EDXREG equ EBXREG + 4
ECXREG equ EDXREG + 4
EAXREG equ ECXREG + 4 //popad
------------------------------------------------------------------------------
RETADR equ EAXREG + 4 //add esp,4
------------------------------------------------------------------------------
EIPREG equ RETADR + 4 //在restart()中几个pop,popad和加4之后,esp指向这里, iretd调用esp指向后面的成员
CSREG equ EIPREG + 4
EFLAGSREG equ CSREG + 4
ESPREG equ EFLAGSREG + 4
SSREG equ ESPREG + 4 u32 ss
}stack_frame;
----------------------------------------------------------------------------------------
P_STACKTOP equ SSREG + 4 //这个参数很重要,top是指堆栈开始的地方,在堆栈最下面.下高上低
//TSS,ring0中的esp指向这里(restart中一开始对esp赋值相加).时钟中断时,从ring1到ring0,读取TSS中ring0中esp,指向进程表的这里,中断会把ring1 进程中的寄存器ss,esp,eflags,cs,ip 压入到进程表这里。 因为push是esp减-4的所以是向上放的。注意:压入是向上压入,弹出是向下弹出。默认是上低下高
P_LDT_SEL equ P_STACKTOP
P_LDT equ P_LDT_SEL + 4
------------------------------------------------------------------------------------------------
restart:
mov esp, [p_proc_ready]
// p_proc_ready指向进程表的指针,存放的是下一个要启动进程的进程表地址 ( P248页)。esp指向一个进程表的首地址
lldt [esp + P_LDT_SEL] //先做了ldt_sel的初始化工作,然后用lldt指令来设置ldtr
lea eax, [esp + P_STACKTOP]
//P_STACKTOP,第一个结构体成员regs的末地址,赋给TSS ring0的esp。我们可以想象在下一次中断发生时,esp将变 成regs的末地址,然后进程ss和esp两个寄存器的值,以及eflags还有cs、eip这几个寄存器值依次被压入堆栈。放到regs这个结构的最后面,注意是regs结构的最后面也就是eipreg,csreg,eflagsreg,espreg,ssreg这几个成员。
mov dword [tss + TSS3_S_SP0], eax
pop gs //pop,eap要加4, esp本身在进程PCB堆栈的最上面. 见mov esp, [p_proc_ready]
pop fs
pop es
pop ds
popad //把retAddr前面e开头的赋值到相应的寄存器
add esp, 4 //跳过retAdd这个成员
iretd //esp指向retAdd下面的eip,irted指令调用esp后面的几个参数.eflags的作用是打开中断 (现在是从ring0到ring1)
相反作用是:时钟中断时,从ring1到ring0,读取TSS中ring0中esp,指向进程表regs的最尾端这里,中断会把ring1 进程中的寄存器ss,esp,eflags,cs,ip 压入到进程表这里。
-----------------------------------------------------------------------------------------------