操作系统原理课程设计微型操作系统的设计.doc
重庆科技学院课程设计报告 院(系):_电气与信息工程学院_ 专业班级: 计科普2008-02学生姓名: 学 号: 设计地点(单位)_ _ I515_ _ _ 设计题目:_ 微型操作系统的设计_ _ 完成日期: 2011年 6月 19日 指导教师评语: _ _ _ _ _ 成绩(五级记分制):_ _ _ 指导教师(签字):_ _ _ 重庆科技学院课程设计任务书设计题目:微型操作系统的设计 学生姓名课程名称操作系统原理课程设计专业班级计科普08地 点 I515起止时间2011年6月12日-2011年6月16日设计内容及要求(1) 配置操作系统编写的所需的环境(虚拟机的建立和相应环境建立),以准备相关的必须工具的准备,并学会相关工具的使用,为以后编写一个微操作系统奠定基础和准备平台。(2) 学习NASM汇编器在本次设计中的使用。(3) 学习裸机启动的过程,消化操作系统引导程序的结构,在此基础上,完成在实模式下从软盘引导计算机的程序编写。(4) 学习本次设计需要的实模式到保护模式切换的相关知识。理解GDT在保护模式的工作机理(5) 编写在保护模式下的引导程序,并用C语言模拟写一个“内核”,并实现在保护模下通过引导程序启动计算机并将该“内核”加载到内存中。最后切换到内核。设计参数(1) 写出编写一个操作系统所需的环境和操作说明书。(2) 总结计算机启动顺序和具体过程。(3) 实现在实模式下系统引导程序的编写。(4) 理解消化实模式到保护模式切换原理以及相关的数据结构和工作过程,并实现之。(5) 完成保护模式下的引导程序,并完成“内核”的加载,并使“内核”运行起来。附加要求:请在设计的课后完成具有进程调度和管理的内核的编写。进度要求6月12日布置任务,对各个任务的基础知识进行讲解6月12日 安装环境,并熟悉相关工具的使用。6月13日完成实模式下引导程序的编写。6月14日完成实模式与保护模式的切换代码的设计。6月15日完成实模式引导程序和内核加载程序编写。6月16日完成答辩和报告撰写。参考资料随任务布置的相关电子文档。其它说明.本表应在每次实施前一周由负责教师填写二份,院系审批后交院系办备案,一份由负责教师留用。.若填写内容较多可另纸附后。3.一题多名学生共用的,在设计内容、参数、要求等方面应有所区别。教研室主任: 指导教师: 摘要操作系统(Operating System,简称OS)是一管理电脑硬件与软件资源的程序,同时也是计算机系统的内核与基石,它为用户执行程序提供方便、最有效的环境。 本设计任务是设计一个微型操作系统。该操作系统首先需要搭建虚拟机环境,为编写一个微操作系统奠定基础。裸机启动的过程,实现实模式下从软盘引导计算机的启动。完成保护模式下的引导程序,并完成“内核”的加载,并使“内核”运行起来。“内核”部分实现键盘中断,中断服务程序读取键盘值并显示出来。关键词:操作系统 虚拟机 裸机启动 键盘中断目 录1 系统需求分析11.1设计内容与目的11.2 设计的实现方案12.总体设计22.1 功能模块图22.2 计算机引导程序22.3 内核键盘中断实现33 详细设计63.1启动程序实现63.2内核键盘中断实现93.3功能实现114. 设计总结135 致谢146 参考文献151 系统需求分析1.1设计内容与目的 设计一个微型操作系统,在实模式下从软盘引导计算机启动,并在保护模式下运行“内核”。通过分析,该设计需要完成以下任务:(1)搭建虚拟机环境,为编写一个微操作系统奠定基础。(2)利用NASM汇编器编译启动汇编程序。(3)完成在实模式下从软盘引导计算机。(4)学习本次设计需要的实模式到保护模式切换的相关知识。理解GDT在保护模式的工作机理。(5)编写在保护模式下的引导程序,并用C语言模拟写一个“内核”,并实现在保护模下通过引导程序启动计算机并将该“内核”加载到内存中。最后切换到内核。1.2 设计的实现方案 本设计完成一个真正意义上的操作系统引导,计算机启动程序将从计算机启动时的16位的实模式转到现在通用的32位的保护模式下。现在的操作系统除了最低层的部份之外,均由高级语言完成,在本设计中也将用高级语言来编写内核。实现的一个内核是用C语言编写的。用汇编写的引导程序,把 C语言写的内核载入并执行,这就是本设计将要完成的主要任务。内核中的键盘中断设计intel 8259a。intel 8259a 可编程中断控制器可以为CPU处理8位优先级中断,而且,无须额外电路即可级联扩展至64位优先级中断处理。通过对8259A的初始化和控制,可以实现在保护模式下的键盘中断。2.总体设计 2.1 功能模块图该设计的功能模块如下图所示: 微型操作系统“内核”实现键盘中断并显示键盘值实模式下从软盘引导计算机中断响应显示从键盘输入值图2.1 功能模块图2.2 计算机引导程序本程序的主要功能是实现实模式和保护模式的切换。(1)切换到保护方式的准备工作 在从实模式切换到保护模式之前,必须作必要的准备。需要建立合适的全局描述符表,并使用GDTR指向该GDT。因为在切换到保护方式时,至少要把代码段的选择子装载到CS,所以GDT中至少含有代码段的描述符。 (2)由实模式切换到保护模式 在做好准备后,从实模式切换到保护模式原则上只要把控制寄存器CR0中的PE位置1即可。 mov eax ,cr0 ; or eax , 1 mov cr0 ,eax 实际情况要比这复杂些。执行上面的三条指令后,处理器转入保护模式,但CS中的内容还是实模式下代码段的段值,而不是保护模式下代码段的选择子,所以在取指令之前得把代码段的选择子装入CS。为此,紧接着这三条指令,安排一条如下所示的段间转移指令 jmp gdt_code_addr:code_32 ; 跳入32位的代码段中 这条段间转移指令 在实模式下被预取并在保护方式下被执行 。利用这条段间转移指令可把保护模式下代码段的选择子装入CS,同时也刷新指令预取队列。从此真正进入保护模式。2.3 内核键盘中断实现要使用中断方式,就必须编写中断处理程序,通过IDT(中断描述符表)让CPU知道此中断的中断处理程序在什么地方,此表的每一个表项对应一个中断,每一个表项都指明此中断的中断处理程序在什么地方。因此首要的任务是要构造一个中断描述符表。 中断描述符表一共可有256项,即256个中断。头三十二项,也就是031号中断,已经被CPU及硬件所占用了,因此只能从第三十三项即32号中断开始构造中断及中断服务程序 。可编程中断控制器(PIC)功能上是中断驱动系统环境下的总管家,决定哪一个输入优先级最高,确定输入请求是否拥有比当前服务级别更高的优先级,并且将决定出的中断通知CPU。为了使中断系统起作用,需要对PIC(可编程的中断控制器)进行编程,PIC 是可编程的中断控制器,它可以处理硬件中断请求,当硬件发生中断时,PIC把中断信号送到CPU,然后CPU处理中断。实际上有两上PIC,第一个PIC1(端口号0x200x21)处理IRQ0IRQ7的请求,第二个PIC2(端口号0xA00xA1)处理 IRQ8IRQ15的请求CPU只知道逻辑意义上的中断,不区分是物理上的软件中断还是硬件中断,因此必须把CPU不知道的物理中断,映射为CPU知道的逻辑意义上的中断。在实模式下,这项工作由BIOS来做,在保护模式下需要自己编程。通过发送一些ICW(初始化命令字)来实现对PICs的控制和初始化。1. 发送 ICW1 到 PIC1(20h) 与 PIC2(A0h) 中 2. 发送 ICW2 到 PIC1(21h) 与 PIC2(A1h) 中 3. 发送 ICW3 到 PIC1(21h) 与 PIC2(A1h)中 4. 发送 ICW4 到 PIC1(21h) 与 PIC2(A1h)中 利用内嵌汇编发送一些ICW(初始化命令字)来实现对PICs的控制和初始化,实现代码如下:_asm_("mov $0x11,%al;out %al,$0x20 n"); _asm_("mov $0x11,%al;out %al,$0xA0 n"); _asm_("mov $0x20,%al;out %al,$0x21 n"); _asm_("mov $0x28,%al;out %al,$0xA1 n"); _asm_("mov $0x04,%al;out %al,$0x21 n"); _asm_("mov $0x02,%al;out %al,$0xA1 n"); _asm_("mov $0x1,%al;out %al,$0x21 n"); _asm_("mov $0x1,%al;out %al,$0xA1 n"); _asm_("mov $0xfd,%al;out %al,$0x21 n"); _asm_("mov $0xff,%al;out %al,$0xA1 n");初始化命令字格式ICW1A0D7D6D6D4D3D2D1D00A7A6A51LTIMADISNGLIC4中断向量地址A7-A5(仅用于MCS-80/85)1:电平触发0:边沿触发地址调用间隔1:4间隔0:8间隔1:单片模式0:级联模式1:需要ICW40不需要ICW2A0D7D6D6D4D3D2D1D01A15/T7A14/T6A13/T5A12/T4A11/T3A10A9A8中断向量地址的A15-A8(MCS-80/85)中断向量地址T7-T3ICW3(主片)A0D7D6D5D4D3D2D1D011:IR输入有从片0:IR输入无从片ICW3(从片)A0D7D6D5D4D3D2D1D0100000ID2ID1ID0从片地址ICW4A0D7D6D5D4D3D2D1D01000SFNMBUFM/SAEOImPM1:特殊全嵌套模式0:全嵌套模式0X:无缓冲模式10:缓冲模式/从片11:缓冲模式/主片1:自动EOI0:一般EOI1:8086/8088模式0:MCS-80/85模式PIC1处理的中断有: 0 系统时钟 1 键盘 2 重定向到IRQ9 (PIC2的IRQ1)3 串口 1(COM2/4) 4 串口 2(COM1/3) 5 声卡 6 软驱 7 并行端口 PIC2处理的中断有:0 实时时钟 1 来自IRQ2 (PIC1) 2 保留 3 保留 4 鼠标 5 数学协处理器 6 硬盘 7 保留 因此,我们只要打开PIC1的1号键盘中断就可以实现实模式下的键盘中断功能。通过这两条内嵌汇编:_asm_("mov $0xfd,%al;out %al,$0x21 n"); _asm_("mov $0xff,%al;out %al,$0xA1 n");就可以在保护模式下打开键盘中断。 3 详细设计3.1启动程序实现BITS 16 ORG 0x7C00 jmp main 数据定义 bootdrive db 0 - GDT 定义,此处定义段及段描述符 gdt: gdt_null: dd 0 dd 0 ; 每个段的描述符是64位(8字节),空描述符的这64位全是0 gdt_code_addr equ $ - gdt ;求得代码段在GDT表中的位置 gdt_code: dw 0xffff ; 段大小为4GB dw 0 ; 基地址(24位) db 0 db 10011010b;属性描述位,指明此是代码段,可读可执 db 11001111b db 0 ; gdt_data_addr equ $ - gdt;求得数据段在GDT表中的位置 gdt_data: dw 0xffff dw 0 db 0 db 10010010b ; 指明此是数据段,可读可写 db 11001111b db 0 gdt_end: gdt_addr: dw gdt_end - gdt - 1 ;GDT表的大小 dd gdt ; GDT 表的位置 main: ;引导程序从此处开始执行 mov bootdrive , dl 得到启动的驱动器号 xor ax , ax ; 设置 DS mov ds , ax ; 清屏 ;mov ax , 3 设置清屏功能号 ;int 0x10 ; 调用 BIOS 10 号中断清屏 .ResetFloppy 重置磁盘,不是必须的,主要是为了安全起见 mov ax , 0 设置重置磁盘的功能号 mov dl , bootdrive ; 选择启动磁盘 int 0x13 ; 调用 BIOS 13 号中断重置磁盘 jc .ResetFloppy ; 如果出错则重试 .ReadFloppy ; 读内核到内存中 0000:9000 (es:bx)处, xor ax , ax ; 设置 es 寄存器 mov es , ax mov bx , 0x9000 mov ah , 2 ; 设置读磁盘功能号 mov dl , bootdrive ; 设置欲读驱动器号 mov ch , 0 ; 磁头号 mov cl , 2 ; 起始扇区号,从第二个扇区开始读, ; 第一个扇区是引导扇区,第二个才是内核所在 mov al , 17 ; 需读入扇区的数量,此处读了17个扇区 ; 是怕内核较大,读少了读不完 int 13h ; 调用 BIOS 13 号中断开始读扇区, ; 此中断会将数据读到es:bx 处 jc .ReadFloppy ; 如果出错则重试(ah中是错误号,为0则没错 mov dl , bootdrive ; 停止驱动器 mov edx , 0x3f2 mov al , 0x0c out dx , al cli ; 关中断 lgdt gdt_addr ; 载入 GDT 的描述符 mov eax , cr0 ; 下面三句设置cr0的第0位(PE位)为1, ; 表示进入保护模式 or eax , 1 mov cr0 , eax jmp gdt_code_addr:code_32 ; 跳入32位的代码段中 BITS 32 code_32: mov ax ,gdt_data_addr ; 以下三句设置DS,ES,SS,FS,GS 为数据段描述表的位置 mov ds , ax mov es , ax mov ss , ax mov fs , ax mov gs , ax mov esp , 0xffff ;设置堆栈的头指针 jmp gdt_code_addr:0x9000 ; 跳入内核, ; gdt_code_addr是定义的代码段的描述符所在的索引 由于我们先前是把内核读到了0x9000的位置, times 510-($-$) db 0 db 0x55 db 0xAA 分析:用NASM对汇编代码进行编译:nasm load.asm -o load.bin编译成功后的load.bin作为操作系统实模式下计算机的引导程序。 开始程序大体流程图如下:定义段及段描述符,并设置段及段描述符的属性 选择启动磁盘 设置读磁盘功能号第二个扇区开始读是否是否出错? 结束 关中断 载入 GDT描述符跳入32位的代码段中图3.1.1引导程序流程图3.2内核键盘中断实现typedef struct unsigned long dword0 ; unsigned long dword1 ; segment_desc; unsigned char* videomem = (unsigned char*)0xb8000; segment_desc idt256; unsigned long idt_desc2; unsigned long idt_addr; unsigned long keyboard_addr; unsigned long idt_offset =0x8; void keyboard_interrupt(); int main() _asm_("mov $0x11,%al;out %al,$0x20 n"); _asm_("mov $0x11,%al;out %al,$0xA0 n"); _asm_("mov $0x20,%al;out %al,$0x21 n"); _asm_("mov $0x28,%al;out %al,$0xA1 n"); _asm_("mov $0x04,%al;out %al,$0x21 n"); _asm_("mov $0x02,%al;out %al,$0xA1 n"); _asm_("mov $0x1,%al;out %al,$0x21 n"); _asm_("mov $0x1,%al;out %al,$0xA1 n"); _asm_("mov $0xfd,%al;out %al,$0x21 n"); _asm_("mov $0xff,%al;out %al,$0xA1 n"); keyboard_addr = (unsigned long)keyboard_interrupt ; idt0x21.dword0 = (keyboard_addr&0xffff)|(idt_offset<<16); idt0x21.dword1 = (keyboard_addr&0xffff0000)|0x8e00; idt_addr = (unsigned long)idt ; idt_desc0 = 0x800 + (idt_addr&0xffff)<<16); idt_desc1 = idt_addr >>16 ; _asm_( "lidt %0n " "sti ":"=m "(idt_desc); while(1);return 0; void keyboard_interrupt()*videomem+ = 'C' *videomem+ = 0x1b; 分析: (1)在Linux下编写好此C语言程序,输入以下命令进行编译: gcc -c xyb.c 其中 -c 表示只编译不链接 ld -o xyb -Ttext 0x9000 -e main xyb.o 其中-o 表示输出文件名,-Ttex 0x9000 表示程序基址定为0x9000 -e main 表示从main()开始执行 objcopy -R .note -R .comment -S -O binary xyb xyb.bin -R .note -R .comment表示移掉 .note与 .comment段 -S 表示移出所有的标志及重定位信息 -O binary xyb xyb.bin 表示由xyb生成二进制文件xyb.bin (2)代码用到了内嵌汇编,如: _asm_("mov $0x11,%al;out %al,$0x20 n");代表的意思为:将0x11的值发送到0x20端口中。(3)程序流程图:实模式下引导计算机进入内核 发送4个ICW 对PIC初始化设定中断屏蔽字,只许键盘中断设置键盘中断处理程序位置 获得整个IDT的位置描述 用lidt指令载入IDT表 进入while(1)等待键盘中断图3.2.1内核程序流程图 3.3功能实现利用winhex工具,操作如下:(1).用winhex工具打开引导程序load.bin,效果如图所示。图3.3.1 编译完成后的引导程序load.bin(2) .用winhex工具打开内核程序xy.Bin,效果如图所示。图3.3.2 编译完成后的内核xy.bin (3)制作软驱利用winhex工具将xy.bin添加到load.bin后面,制作os.img;(4)启动微型操作系统如下:利用虚拟机工具 virtual PC,启动后选择菜单:capture floppy disk image 成功启动后,按下键盘任意键,可以看到进入中断服务程序ISR显示内容如下:说明进入ISR成功,键盘中断基本成功。图2.3.3进入ISR后的显示4. 设计总结通过本次微型操作系统的设计巩固了平时学习中的理论知识,同时对操作系统底层编程有了进一步的了解。本次课程设计实现了在实模式下对计算机的引导,内核部分用C语言写,在实模式下启动计算机后就开始运行内核部分。内核实现中断键盘响应和打印等功能。由于时间比较紧迫,仍有些功能没有实现。出现的问题如下:在内核中,能响应键盘中断,但只能进入一次,之后就没法再响应键盘中断了。这是内核部分的缺陷,通过不断调试,仍然无法解决这个问题,最后只能实现这个简单的功能。但不管怎样,这次课程设计还是学到了很多知识。5 致谢首先感谢老师对我这次课程设计的辛勤帮助,使我对基本理论知识有了更深刻的掌握。这学期我学习最努力的就是操作系统这门课,一直在努力学懂操作系统的基础知识,谢谢老师这学期对我的辅导,让我对操作系统有了更加深入的理解,我以后仍将继续学习操作系统。感谢在本次课程设计中帮助我的同学。感谢学校和院系给我这次课程设计的机会。6 参考文献1、操作系统(第2版),孟庆昌,牛欣源,电子工业出版社,2010;2、操作系统基础知识,哈工大C语言论坛,2008;