多任务程序结构和工作原理
该模拟内核由两个程序文件组成,boot.s和 head.s 。 boot.s主要是把head,s中的代码加载进内存中。
并在设置好临时GDT表等信息后,把处理器设置成运行在保护模式下,然后跳转到head代码处去运行内核代码。
实际上boot.s程序首先会把这段head代码移动到内存0开始处,最后设置控制寄存器CR0中的开启保护运行模式标志,并
跳转到内存0处开始执行head代码。
不能让boot程序把head代码从软盘或者映像文件中,直接把代码加载到内存0处。因为加载过程需要使用rom bios提供的中断过程,而中断向量表存储在
内存的0处,并且在内存的1 KB处是BIOS程序使用的数据区。
1 head.s 代码初始化的主要工作:
(1) 重新设置GDT表
(2) 设置系统定时器芯片
(3) 重新设置IDT表,并且设置时钟和系统调用中断门。
(4) 移动到任务A中执行。
![](http://www.cppblog.com/images/cppblog_com/jake1036/65.jpg)
两个任务在LDT中代码段和数据段描述符的内容也都设置为 : 基地址为0x0000;段限长值为0x03ff ,实际长度为4MB。
使用IRET 来执行相应的任务
由于处于特权级0的代码不能直接把控制权转移到特权级3上的代码上执行,但中断返回是可以的。,因此当初始化GDT IDT 和定时器芯片之后,我们就需要用利用中断返回指令IRET来启动运行第一个任务。具体实现方法如下:
在初始堆栈init_stack 中人工设置一个返回环境。即把任务0的TSS段选择符加载到任务寄存器LTR中,LDT段选择符加载到LDTR中,把任务0的
用户栈指针和代码段指针 以及
标志寄存器压入栈中,然后执行返回指令IRET。 该指令会弹出堆栈上的堆栈指针作为任务0用户栈指针,恢复假设的任务0的标志寄存器内容,并且弹出栈中代码指针放入 CS:EIP 寄存器中,从而开始执行任务0的代码,实现了从特权级0到特权级3的控制转移。