毕业论文-x86保护模式下简易操作系统的设计与实现_第1页
毕业论文-x86保护模式下简易操作系统的设计与实现_第2页
毕业论文-x86保护模式下简易操作系统的设计与实现_第3页
毕业论文-x86保护模式下简易操作系统的设计与实现_第4页
毕业论文-x86保护模式下简易操作系统的设计与实现_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、大连东软信息学院本科毕业设计(论文)论文题目论文题目:x86保护模式下简易操作系统的设计与实现 系 所: 电子工程系 专 业: 电子信息工程(嵌入式系统工程方向) 学生姓名: 学生学号: 指导教师: 导师职称: 讲师 完成日期: 2014年 5月 2日 大连东软信息学院Dalian Neusoft University of Information大连东软信息学院毕业设计(论文) 摘要 IVx86保护模式下简易操作系统的设计与实现摘 要简易的操作系统从只有二十多行的引导扇区代码运行并出发,按部就班地展现出一个微型操作系统框架的完成过程。不但关注系统代码的本身,也同时注重完成这些系统代码的过程以

2、及思路。有别于其他的理论型,本次项目展示的是一幅实践下的路线图。在路线图的指引下,可以按部就班的完成各个模块功能,可以消除在独自面对整个操作系统数万行代码时的挫败感和迷茫。需注意的细节问题在一步步的开发中得到了分析,了解和认识系统的核心原理就依赖于这些实践中的分析,最终使整个开发过程少走一些弯路。这其中每一个步骤都是以前一步骤的工作成果作为基础,从而展现一项新的功能。而在功能内部,一项比较大的功能被分解成许多小的工程,通过完成每个小的工程,从而可以不断获得阶段性的项目成功,最终让整个开发过程变得有趣并且轻松。系统完成后在Bochs这一开源虚拟机下得到成功运行,实现了一个系统应有的基本功能,把书

3、籍中的理论实践化,所谓麻雀虽小五脏俱全,不可否认的是系统中应该还存在着潜在的Bug,因为只要是程序就一定会有漏洞,这就得在后期的测试中找出并加以修复。关键词:操作系统,开发,代码,扇区大连东软信息学院毕业设计(论文) Abstract Design and implementation of a simple operating system in x86 protected modeAbstractEasy operating systems and multi-line starting from only twenty boot sector code , showing step by

4、 step through the process of a miniature operating system framework. Not only concerned about the system code itself , and also pay attention to the completion of these processes and system code idea . Unlike other theoretical model , this project demonstrates that a practice under the roadmap . Und

5、er the guidance of the roadmap , step by step to complete each module can function, you can eliminate the entire operating system in the face alone tens of thousands of lines of code when frustration and confusion . Should pay attention to the details of the problem is a step in the development of t

6、he analysis , understanding and knowledge of the core principles of the system will depend on the analysis of these practices , and ultimately the entire development process, take some detours . Each step which previous work product of the previous step as the base , which show a new feature . The f

7、unctional interior , a large function is broken down into many small projects , through the completion of each small project , so you can continue to receive periodic project success , and ultimately the entire development process becomes fun and easy .Upon completion of the system obtained under th

8、e open-source Bochs virtual machine to run successfully, to achieve the basic functions of a system should be put in a book of theory and practice, the so-called small but perfectly formed, it is undeniable that the system should still exist potential Bug, because as long as the program is bound to

9、have loopholes, which have to find and fix in later tests.Key words: System, Develop,Code,Sector大连东软信息学院毕业设计(论文) 目录目 录 TOC o 1-3 u 摘 要 PAGEREF _Toc386463069 h IAbstract PAGEREF _Toc386463070 h II第1章绪 论 PAGEREF _Toc386463071 h 11.1 课题研究背景与意义 PAGEREF _Toc386463072 h 11.2 课题研究内容与方法 PAGEREF _Toc38646307

10、3 h 11.3 课题研究现状 PAGEREF _Toc386463074 h 2第2章关键技术介绍 PAGEREF _Toc386463075 h 42.1 关键技术一 PAGEREF _Toc386463076 h 42.2 关键技术二 PAGEREF _Toc386463077 h 42.3 关键技术三 PAGEREF _Toc386463082 h 82.4 关键技术四 PAGEREF _Toc386463085 h 102.5 关键技术五 PAGEREF _Toc386463091 h 142.6关键技术六 PAGEREF _Toc386463092 h 142.7关键技术七 PAG

11、EREF _Toc386463093 h 152.8关键技术八 PAGEREF _Toc386463094 h 16第3章系统需求分析 PAGEREF _Toc386463095 h 173.1 架构概述 PAGEREF _Toc386463096 h 173.2 系统功能需求 PAGEREF _Toc386463097 h 173.3 系统开发环境 PAGEREF _Toc386463098 h 173.4系统可行性分析 PAGEREF _Toc386463099 h 173.4.1 技术可行性 PAGEREF _Toc386463100 h 17第4章系统设计 PAGEREF _Toc38

12、6463101 h 184.1 系统设计指导原则 PAGEREF _Toc386463102 h 184.2 软件设计原则 PAGEREF _Toc386463103 h 18第5章系统实现 PAGEREF _Toc386463104 h 195.1环境配置 PAGEREF _Toc386463105 h 195.2 工作环境搭建 PAGEREF _Toc386463106 h 195.2.1 主要实现介绍 PAGEREF _Toc386463107 h 195.3引导扇区加载 PAGEREF _Toc386463108 h 215.3.1主要流程介绍 PAGEREF _Toc38646310

13、9 h 215.4 Loader加载 PAGEREF _Toc386463110 h 225.4.1主要流程介绍 PAGEREF _Toc386463111 h 225.5 Kernel加载 PAGEREF _Toc386463112 h 295.5.1主要流程介绍 PAGEREF _Toc386463113 h 29第6章系统测试 PAGEREF _Toc386463114 h 326.1 测试方法和技术 PAGEREF _Toc386463115 h 326.2 测试设计 PAGEREF _Toc386463116 h 326.3 测试实施 PAGEREF _Toc386463117 h

14、326.3.1 单元测试 PAGEREF _Toc386463118 h 32第7章结论 PAGEREF _Toc386463119 h 34参考文献39致 谢40大连东软信息学院毕业设计(论文)- 第1章绪 论1.1 课题研究背景与意义操作系统是计算机系统的重要组成部分,操作系统课程是计算机教育的基础课程。作为一门计算机专业的基础的核心课程,不仅各个高等院校相关计算机的专业学生必须学习并掌握它,而且从事IT行业的人员也最好需要深入的了解它。进入上世纪九十年代以后,计算机相关科学技术得到了突飞猛进的发展,操作系统又是计算机领域最活跃的分支之一,操作系统的新型的概念、新型的技术以及新型的方法层出

15、不穷,促使整个现代操作系统发生了巨大的变化。作为一个普通用户,熟悉操作系统会事半功倍。对于计算机相关专业的来说,操作系统是计算机体系中重要的一个组成部分。第一点,操作系统的功能模块应用在很多领域。如开发并发的程序:Web ServiceS,分布式的系统和分布网络,通过调查你会发现,这些IT领域大量使用了操作系统的概念和技术。如果你学好了操作系统,最终你就可以对你做的事情更加有信心。第二点,操作系统的开发技巧也应用于很多领域,如抽象、缓存、并发等。操作系统简单来说就是实现抽象:进程抽象、文件抽象、虚拟存储抽象等。而很多领域也使用抽象。如数据结构和程序设计就大量使用了抽象,记得抽象数据类型吗?记得

16、抽象类吗?很多地方都用缓存。你开发Web应用要不要缓存呢?这些你都需要。如果学习操作系统,你就掌握了这些知识。触类旁通,你学习别的知识时就容易多了。1.2 课题研究内容与方法中央处理器是数字处理系统中的一个重要环节。在我看来,单片机、微处理器、数字信号都可以称作是中央处理器,只是它们的侧重点有所不同罢了。具体来说,传统意义上的单片机更偏重于嵌入式的计算,比如说我们经常使用的51单片机、arm处理器、arv处理器芯片中不仅仅含有了运算和控制功能,它还涵盖了时钟处理、串口并口、通用串行总线、i2c总线等等外部资源。数字信号呢,中央处理器一般只是作为数字信号的一个核存在,它通常还会包含另外一个核,专

17、门用于数字信号的处理工作。而微处理器,也就是我们经常说的个人电脑上的处理器,它的工作范围比较单一,专注于计算和控制功能的处理,因此一般来说在这方面的性能上面,单片机和数字信号都是不能和它相比的,有了南桥芯片和北桥芯片的帮助,个人计算机的微处理器就可以专注于自己的本职工作了,效率上面也会有一个很大的提高。寄存器中央处理器内部的基本资源。不管处理器的代码执行到什么时候,这些资源都是共享的,所以在处理器发生中断、函数调用、线程切换的时候,都需要对这些寄存器进行保护,常用的基本措施就是把把它们保存到临时堆栈当中去。堆栈寄存器记录了当前堆栈使用到了什么地方,个人电脑寄存器则记录当前代码跑到了什么地方,下

18、一条指令在什么地方等。状态寄存器则保存了当前处理器的执行情况,包括计算有没有溢出、中断是关还是开、有没有o除数异常等等。至于运算寄存器就因处理器而异了,有的处理器寄存器比较少,比如说x86的寄存器;有的处理器寄存器就比较多,比如说power pc。运算寄存器的用途很多,比如说数据访问、计算、移位、返回计算结果等等。不管是什么处理器,指令中断部分的内容都是少不了的。尝试想一想,如果一颗处理器只知道不停地运行,那么它的执行效率实际上是很低的。拥有了中断的处理器不仅使得处理器可以和更多的外设输入输出打交道,还可以极大地提高自身运行的效率。不同的处理器处理中断的方法其实都差不多,在整个处理器的地址空间

19、里面,通常在低地址区域会有一张中断向量表,表中每一项记录了每一个中断对应的处理函数。所以,只要中断发生时,处理器就会首先将下一条PC地址压入堆栈,接着跳转到中断向量表中对应的中断地址处执行的相应的处理函数。这个过程是处理器自动完成的,不需要我们关心。这样对我们来说,它和处理器中的函数调用其实没有什么区别。等待中断处理结束后,我们使用ret返回指令返回到之前压入的那个IP地址的地方,继续执行下面的代码。整个过程就看似中断根本没有发生过一样。1.3 课题研究现状 操作系统研发是一项非常艰难的工作。开发一个成功的微型操作系统,必须组织一支具有很强的实力和经验丰富的专业团队,还要有大量的资金投入。举微

20、软开发Windows NT操作系统为例,微软组织了6000多人的开发队伍,投入80亿美元,历时7年,开发并不算很成功,连微软官方自己都承认发布了一个失败的版本;上世纪90年代,IBM在开发OS-2操作系统时也摔过一次筋斗,无疾而终走向失败。国内某些公司低估操作系统开发的复杂性和艰巨性,他们凭借几十个人人或一、二百人的开发队伍(技术力量比较薄弱,没有什么开发经验),投入更是非常少得可怜,花2、3年功夫,便推出自称是“完全自主开发”的操作系统,有人更扬言要“甩掉开源搞自主”,他们获得成功的可信度其实很低。开源为开发操作系统的研发提供机遇。透明和公开的开源操作系统问世,使得对操作系统内部架构不太知晓

21、(也无法去深入了解)的开发人员,获得了了解并掌握操作系统体系架构的机遇,也促使他们在这方面的知识产生飞跃;基于开源模式的操作系统可为开发工作节约大量人力、物力、财力和时间,可使操作系统的开发者们最终得以站在巨人肩膀上前进。因此开发基于开源的操作系统必然是一条正确的开发路线。最终这几年,很多基于Linux内核的操作系统相继问世,如Android、WebOS、MeeGo等,便是采取了基于Linux内核的技术发展路线。接受国家专项费用资助的前提是,该项基础软件必须是自主开发的;如上述,国内目前开发操作系统宜采用基于开源的方式;有人质疑:开源与自主是否对立?!要弄清楚并处理好这个问题,须从分析操作系统

22、体系架构出发。操作系统的体系架构,由其底层(Base Layer)、中间件层(Middle Ware Layer)、用户体验层(User Experience Layer)以及独立配置的软件模块,如安全模块(Secarity Module)所构成。系统底层主要是其内核(Kernel);对中间件层,从开发者角度看,主要指的是开发系统环境和运行系统环境(Development Environment and Runtime Environment),从用户的角度看,主要指各种各样的功能模块(Functional Modules)或应用程序架构(Application Framework);用户的体

23、验层(UE=UI+Applicaions),由用户操作界面和各种应用程序所构成的。因此,操作系统是一个多层次的架构、多元化协议、许多构件构成的系统。很多操作系统是基于Linux开源内核来研发的。Linux基金会(Linux社区组织)负责“Linux内核”官方(Official)或主要的各款通用版本的研发、发售和维护工作。对基于Linux开源内核的操作系统的开发者来说,可选择某款Linux内核版本作为自己操作系统的内核雏形,如果要对主干版本内核进行修改以形成自己的分支内核版本时,必须将其修改部分在规定时间内反馈给主干版本的维护管理者,取得他们对修改的许可,并在主干Linux内核中登记并注册,最终

24、使这个分支内核版本成为Linux开源内核大家庭中一员。大连东软信息学院毕业设计(论文)第2章关键技术介绍2.1 关键技术一(1)“实模式-保护模式-实模式”的转换过程关中断打开地址线A20置cr0寄存器的末位为1实现跳转,进入到保护模式(2)“保护模式-实模式”的跳转从保护模式下的32位代码段跳转到16位代码段在16位代码段下初始化所有段寄存器置cr0的末位为0实现跳转,返回到实模式(3)“实模式-保护模式-实模式”的跳转过程下面是“实模式-保护模式-实模式”的跳转过程图图 关键技术二(1)分页机制图2.2.1如何通过分页管理的机制,将线性地址转换为实际的物理地址:图2.2.2地址转换使用两级

25、的页表,第一级页表叫做页目录,页表大小为4KB,存储在一个物理页当中,每个表项长度为4字节长,总共有1024个表项。每个表项对应第二层的一个页表项,第二级的每一个页表项也有1024个表项,每一个页表项对应一个物理页。页目录表的表项简称为PDE(Page Directory Entry),页表的表项简称为PTE(Page Table Entry)。内存线性地址转换物理地址的具体步骤是:首先从寄存器cr3指定的页目录中根据线性地址的高10位得到页表。其次在页表中,根据线性地址的第1221位得到物理页首地址。最后这个首地址,加上线性地址的低12位便得到了物理地址。图2.2.3其中特别需要注意的几个属

26、性:首先P存在位,表示将当前条目所指向的页或页表是否在物理内存中。当P=0的时候表示页不在内存中,并且如果此时处理器试图访问此页,将会产生缺页异常(fault exception, #PF);P=1则表示页在内存中。其次A指示页或页表是否被访问。此位往往在页或页表刚刚被系统加载到物理内存中时被内存管理程序清零,中央处理器会在第一次访问此页或也表时设置该位。并且,处理器并不会自动清除这个标志位,只有软件才能清除它。同时在时钟页面置换算法中,需要通过该位来标记此页面是否已经被访问。接着D指示页或页表是否被写入,此位往往在页或页表刚刚被系统加载到物理内存中时被内存管理程序清零,中央处理器会在第一次写

27、入此页或页表时设置此位的标志。而且,处理器并不会自动清除此位的标志,只有通过软件能清除它。由于该标志位的存在,系统当往某页写入内容时,并不需要将其同步到硬盘上,只有当该页被系统置换出时,判断该位D=0,则表示该页没有被系统写入,系统则不需要将其写入磁盘;D=1,则表示该页已被系统写入,则需要将其写入到硬盘。图2.2.4其中各属性位与PDE中具有相同的含义。cr3寄存器中的高20位将是页目录表首地址的高20位,PDE页表的高20位是页表首地址,PTE页表的高20位是物理页的首地址。在保护模式下,内存寻址的范围是0-4GB,为什么却系统用20位来存储这些首地址呢? cr3寄存器中的高20位是页目录

28、表首地址的高20位,页目录PDE表首地址的低12位将会是0,这样就保证了页目录表PDE会是4KB对齐的。同理,页目录PDE中的页表基址(Table Base Address),以及PTE页表中的物理页基址(Page Base Address)也是用高20位来表示4KB内存对齐的页表和页。在初始化页目录表和页表之后,要让cr3寄存器指向页目录表,然后设置cr0寄存器的PG位。图 关键技术三中断机制中断产生的原因如何将中断向量与中断服务程序关联起来外部中断2.3.1中断中断产生的原因有两种:一是外部中断,就是由硬件产生的中断;另一种是由指令int n产生的中断。2.3.2如何将中断向量与中断服务程

29、序关联起来实模式下:图2.3.1这个过程很简单,就是通过int n中的n,去中断向量表中获取该中断的中断服务程序的CS和IP,然后加载CS和IP,跳转到中断服务程序。其中(n*4)(n*4+1)中保存着中断服务程序入口地址的偏移量IP(n*4+2)(n*4+3)中保存着中断服务程序入口地址的段地址CS。保护模式下:图2.3.2在保护模式下,不存在中断向量表,而是使用中断描述符表-IDT(Interrupt Descriptor Table)。 中断描述符表,类似于GDT、LDT,实际上就是一个描述符表。中断门描述符、陷阱门描述符、任务门描述符构成了IDT中的三种描述符: IDT的作用是将每一个

30、中断向量和一个描述符对应起来,而描述符中保存的是中断服务程序的基地址和偏移量。2.3.2外部中断外部中断的情况有些复杂,因为需要建立硬件中断与向量号之间的对应关系。外部中断分为不可屏蔽中断(NMI)和可屏蔽中断两种,分别由CPU的两根引脚NMI和INTR来接受。图2.3.38259A是可编程中断控制器,对它的设置并不复杂,是通过向相应的端口地址写入特定的ICW(Initialization Command Word)来实现的。主8259A对应的端口地址是20h和21h,从8259A对应的端口地址是A0h和A1h。ICW共有4个,每一个都是具有特定格式的字节。8259A初始化过程为:(1)往端口

31、20h(主片)或A0h(从片)写入ICW1(2)往端口21h(主片)或A1h(从片)写入ICW2(3)往端口21h(主片)或A1h(从片)写入ICW3(4)往端口21h(主片)或A1h(从片)写入ICW40001 0001 主8259A, ICW1需要ICW4,级联8259,8字节中断向量,edge triggered模式,PC系统0001 0001 从8259A, ICW1需要ICW4,级联8259,8字节中断向量,edge triggered模式,PC系统0010 0000 主8259A,ICW280 x86系统,IR0对应中断向量Ox200010 1000 从8259A,ICW280 x

32、86系统,IR8对应中断向量Ox280000 0100 主8259A,ICW3IR0,IR1,IR3,IR4,IR5,IR6,IR7,无从片;IR2有级联从片0000 0010 从8259A,ICW3级联于主8259的IR20000 0001 主8259A,ICW40000 0001 从8259A,ICW41111 1111 主8259,OCW1屏蔽主8259所有中断1111 1111 从8259,OCW1屏蔽从8259所有中断2.4 关键技术四多进程实现2.4.1.明确多进程概念 大家都知道,现在的操作系统都是支持多进程的,即一个CPU可以支持多个进程。这个又是什么情况?让我来修改一下上面的

33、场景。周末,张先生想为他心爱的老婆做一道菜牛肉排骨汤,他有做这道菜的菜谱,厨房里也有牛肉排骨,味精,香料等,张先生开始做牛肉排骨汤,做着做着,他的儿子的手被刀子划破了,哭着跑到爸爸这里来诉苦,这时候,张先生停下手里的活,在菜谱上记下自己做到了哪里,然后拿出一本急救手册,按着上面的指示,把儿子的手伤包扎好之后,他回到厨房继续做自己的牛肉排骨汤。在这个场景中,就包含了两个进程,进程一是做牛肉排骨汤,进程二是为儿子包扎伤口。张先生(CPU)先是执行的进程一,在进程一还米有结束之前,暂停进程一,去执行了进程二。执行完进程二,回到继续执行进程一,直至进程一结束。这个过程就成为进程之间的切换。下面我们通过

34、一张图片来介绍多进程之间的关系:图2.4.1图(a):一个包含4个进程的进程表图(b):4个进程是完全独立的图(c):4个进程进行切换,但任意时刻只有一个进程在运行由此,我们得知,进程,从宏观上来说,有自己的目标,又受控于进程调度模块的控制。从微观上来说,有自己的代码和数据,同时也拥有自己的堆栈。但又利用系统的资源。2.4.2执行一个进程需要什么图2.4.2每个进程包含自己的代码,数据,和堆栈,并且都服从进程调度模块进行调度。2.4.3多个进程如何调度多进程之间的调度是由进程调度模块来完成的。我们首先需要了解进程的状态,下图为3种状态之间的关系:图2.4.3其中条件2是调度模块选择其中某一个进

35、程运行。条件3是时钟中断发生,调度模块将正在运行的进程调入到就绪队列2.4.4 进程的上下文环境在张先生去为儿子包扎伤口时,他需要在菜谱上记录下自己做牛肉排骨汤做到什么地方,以便回来之后继续做。同理,操作系统在进行系统切换时,也同样要记录下该进程的上下文环境。于是我们创建了一个数据结构-进程控制块(ProcessControl Block),它主要包括以下几方面信息:1、进程标识符 name:每个进程都必须有一个唯一的标识符,可以是字符串,也可以是一个数字。2、进程当前状态 status:说明进程当前所处的状态。为了管理的方便,系统设计时会将相同的状态的进程组成一个队列,如就绪进程队列,阻塞进

36、程则要根据等待的事件组成多个等待队列,如等待打印机队列、等待磁盘I/O完成队列等等。3、进程相应的程序和数据地址,以便把PCB与其程序和数据联系起来。4、进程资源清单。列出所拥有的除CPU外的资源记录,如拥有的I/O设备,打开的文件列表等。5、进程优先级:优先级的大小体现了进程的重要程度,常常是用户和系统进行设置的。6、现场保护区:如果进程遇到一些特殊的情况不能继续占用CPU的时间的时候,必须从时间片中切换出来,这个时候保存进程的各种状态信息就显得尤为必要,当进程再次被切换到的时候才可以继续运行。7、各种同步的对象,比如事件,信号量等等。8、进程的PCB结构体指针,指针指向当前的进程状态结构。

37、9、最后是一些相关的其他信息,比如中断时间片等等。每个进程有自己的进程控制块,我们将这些进程控制块组织到一起,存储在一个叫进程表(Process Table)的结构数组中。2.5 关键技术五(1)进程间通信:新增加一个操作系统进程,和TESTA进程进行通信传输,通信的流程应该是这样的,如果首先执行到系统的进程,发送通信消息,那么会触发内中断到ring0操作级,完成发送信息所需要的动作,之后回到系统的进程上下文。待进程切换到用户进程TESTA,等待接受消息,也会触发系统内中断,会到ring0的级别,完成接受所需要的操作执行动作,之后回到用户进程TESTA。现在切换到TYY(多控制台),task_

38、sys任务和用户进程依次执行(时钟的中断),并且TYY控制台和task_sys任务的优先级最高。当遇到操作系统的调用(比如get_tick,printf,sendrec),切换到ring0的操作级别,执行到内核态不能被时钟中断打断,执行后返回刚才的进程。每当遇到有用户键盘输入,和上面的执行过程一样,往键盘缓冲区输入键盘扫描码。2.6关键技术六(1)堆栈段内存的运作方式堆栈段在实模式和保护模式下的工作方式是相同的,下面我只介绍在实模式下的工作执行方式: 其中SS端寄存器为堆栈段寄存器,用来存储堆栈段的初始化地址;SP寄存器堆栈指针寄存器,用来存储堆栈段的栈顶偏移量。内存堆栈段初始化的工作如下:图

39、2.6.1SS段寄存器定位到堆栈段的起始地址(基地址,低地址),栈底BP位于堆栈段的有效地址的最末端(高地址)。SP寄存器初始化为堆栈段的大小,SS:SP指针永远指向堆栈的栈顶。在初始化时,SS:SP指针指向堆栈段的最高地址(此时,栈底和栈顶都指向这一内存地址)。随着压入元素,SP寄存器不断变小,进而SS:SP指针代表的栈顶地址变小,不在等于栈底的地址,而是逐渐的靠近堆栈段的起始地址,当SP寄存器为0时,SS:SP指针代表的栈顶地址与SS:0000代表的堆栈段的起始地址相等,进而确定栈满,处理器也是通过判断SP 柱面号,起始扇区,磁头号);设扇区号为x; 柱面号 = y 1; x 商 y ;

40、= 磁头号 = y & 1; 每磁道扇区数 ; 余 z = 起始扇区号 = z + 1;开辟出两个字节的堆栈区间保存要读取的扇区数:bytebp-2push bpmov bp, spsub esp, 2mov bytebp-2, cl;将参数cl,存储在bytebp-2,将要读取扇区的个数。push bx;保存bx,因为下面要使用bx进行计算。mov bl, ds:BPB_SecPerTrk;bl:除数=18;ax存储的是扇区号,bl是每磁道扇区数,执行ax/bl=alah,;即商y在al中,商z在ah中。div blinc ah;ah(z)+,即起始扇区号=z+1,mov cl, ah;将a

41、h值赋值给cl,中断int 13h中,cl保存的恰好是起始扇区号mov dl, al;将al(y),赋值给dhshr ah, 1;对al(y)进行右移一位,即得到柱面号=y1,mov ch, al;然后将al赋值给ch,在中断int 13h中,ch保存着柱面(磁道)号and dh, 1;将dl(y)进行&1运算,即得到磁头号=y&1,在中断int 13h中,dh保存着磁头号pop bx;恢复bx值;最后到此为止,“磁道(柱面)号(ch),起始的扇区号(cl),磁头的标号(dh),缓冲区地址(es:bx)”全部已准备就绪mov dl, BS_DrvNum;在中断int 13中,dl保存着驱动器号

42、。此时dl=BS_DrvNum=0.GoOnReading:;下面对ah,al进行赋值,ah=2,al=要读取的扇区数,前面将参数cl存储在bytebp-2,现在从这里重新获取并赋值给al。mov ah, 2mov al, bytebp-2;中断int 13一切准备就绪,然后执行int 13int 13hjc.GoOnReading;如果读取扇区错误,CF标志会被置为1,这时就不断地读,直到读取正确为止。add esp, 2;恢复堆栈pop bp在软盘中寻找Loader.bin文件:(1)结合FAT12数据结构,从中我们可以知道,要寻找一个文件,首先需要在根目录区中寻找该文件的根目录条目;然后

43、根据根目录条目获取文件开始簇数(也就是在数据区中存储的扇区);最后读取文件内容到内存。(2)在根目录区中寻找该文件的根目录条目首先要知道根目录区的开始扇区号是19,也就是说从第19扇区开始,根目录区占用扇区总数为14,也就是说,如果不能发现Loader.bin,需要将14个扇区都进行查找,于是需要一个大的循环在外围,控制着扇区的读取。紧接着,我们每读取一个扇区,一个扇区是512个字节,一个根目录条目占32个字节,故一个扇区中存在512/32=16个根目录条目,所以需要添加一个循环,控制根目录条目的变化,从016进行循环。最后,针对每一个根目录条目,我们只是要比较文件名,一个根目录条目的文件名占

44、用11个字节,所以需要对每一个字节与LOADER BIN中的每一个字节进行比较,所以还是要添加一个循环,来控制字符的变化,即从011.用C语言来表示该问题就是:for( i = 根目录区的起始扇区号(19); i 根目录区占有的扇区数(14); i+) for( j = 0;j 一个扇区内存储的根目录条目个数(512/32=16); j+) for(k =0; k 根目录条目中文件名占用的空间(11个字符); k+) if(k=10)jmp LABEL_FILENAMEFOUNDif(ds:si= es:di) si+; di+;else break; (3)下面让我们来分析代码:首先需要介绍

45、下面可能需要用到的几个变量值:nBaseOfLoaders equ 09000h ;LOADER.BIN被加载到的位置段地址nOffsetOfLoaders equ 0100h ;LOADER.BIN被加载到的位置偏移地址nRootDirSectors equ 14 ;根目录占用空间(BPB_RootEntCnt*32+511)/512nSectorNoOfRootDirectory equ 19 ;Root Directory 的第一个扇区号变量定义:nRootDirSizeForLoop dw RootDirSectors ;Root Directory占用的扇区数,在循环中会递减至0nS

46、ectorNo dw 0 ;要读取的扇区号bOdd db 0 ;奇数还是偶数字符串:szLoaderFileName db LOADER BIN, 0 ;LOADER.BIN之文件名;调用中断int 13h,实现软驱复位xor ah, ahxor dl, dlint 13h;下面在软驱A盘的根目录中寻找LOADER.BIN;wSectorNo表示要读取的扇区号,SectorNoOfRootDirectory;表示根目录区的开始扇区号=19mov wordwSectorNo, SectorNoOfRootDirectoryLABEL_SEARCH_IN_ROOT_DIR_BEGIN:;wRoot

47、DirSizeForLoop=RootDirSectors,表示根目录占用的扇区数,即表示要读取的扇区数;也就是;最外部循环中的控制变量(相当于i)。;判断根目录区所有扇区是不是已经读取完毕,如果读完表示没有找到LOADER.BIN,;跳入到LABEL_NO_LOADERBIN执行,否则,减1。cmp wordwRootDirSizeForLoop, 0jzLABEL_NO_LOADERBINdecwordwRootDirSizeForLoop;为ReadSector函数准备参数,从第ax个Sector开始读,将cl个Sector读入es:bx中mov ax, nBaseOfLoadermov

48、 es, ax;es-BaseOfLoadermov bx, OffsetOfLoader;bx-OffsetOfLoader,于是es:bx=BaseOfLoader:OffsetOfLoadermov ax, wSectorNo;axLOADER BINmov di, OffsetOfLoader;es:di-BaseOfLoader:OffsetOfLoader=es:bx 即es:di指向存储的该扇区数据cld;一个扇区是512个字节,一个根目录项占32个字节,故512/32=16,因此需要比较16个根目录项的文件名,;故赋值dx=16,由dx来控制循环次数mov dx, 10hLAB

49、EL_SEARCH_FOR_LOADERBIN:;判断dx是否为0,0意味着这个扇区内的所有根目录项进行比较完毕,然后跳入到下一个扇区,继续进行比较,;dx=0,则跳入LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR;否则,dx-cmp dx, 0jzLABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIRdec dx;一个根目录项的文件名占用11个字节,故必须对其每个字节与LOADER BIN一一对比;故赋值cx=11,由cx来控制循环次数mov cx, 11LABEL_CMP_FILENAME:cmp cx, 0jz LABEL_FILENAME_FOUND

50、;如果cx=0,意味着11个字符都相等,表示找到,跳转到LABEL_FILENAME_FOUNDdec cx;否则,cx-lodsb;ds:si-al,ds:si指向的是字符串LOADER BINcmp al, bytees:di;进行一个字符的比较,如果相等,则比较下一个字符,jz LABEL_GO_ON;跳入到LABEL_GO_ONjmp LABEL_DIFFERENT;只要发现有一个不相等的字符就表明本Directory Entry不是我们要;找到LOADER.BIN,跳转到LABEL_DIFFERENT,进如下一个Directory Entry比较。LABEL_GO_ON:inc di

51、;将di+,进行一个字符的比较。jmp LABEL_CMP_FILENAME;跳转到LABEL_CMP_FILENAME这个标志,继续进行文件名字符串的比较。LABEL_DIFFERENT:;di&=E0是为了让它指向本条目开头,di初始化为某个条目开头,;在比较过程中,会将它不断增1,当失败之后,必须进行重新初始化;因为一个条目占用32个BYTE,故而and di,0FFE0h add di, 20h;之后,di就指向了下一个条目and di, 0FFE0hadd di, 20h;重新初始化si,使其指向LOADER BIN的开始位置mov si, LoaderFileNamejmp LAB

52、EL_SEARCH_FOR_LOADERBIN;跳转到LABEL_SEARCH_FOR_LOADERBINLABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:add wordwSectorNo, 1;将要读取的扇区号+1,进行下一个扇区的比较jmp LABEL_SEARCH_IN_ROOT_DIR_BEGIN;跳转到LABEL_SEARCH_IN_ROOT_DIR_BEGIN,开始一个扇区的比较;如果最后没有找到LOADER BIN,则显示“NO LOADER”字符串来表示。LABEL_NO_LOADERBIN:mov dh, 2;NO LOADERcall DispStrs

53、;显示输出字符串%ifdef_BOOT_DEBUG_mov dh, 2;NO LOADERcall DispStr;显示输出字符串mov ax, 4C00hint 21h;没有找到LOADER.BIN,返回到DOS%elsejmp $;没有找到LOADER.BIN,死循环在这里%endif;如果找到LOADER BIN文件,则跳转到LABEL_FILENAME_FOUNT标记,然后进行第二步骤,从Directory Entry目录中读取文件在数据区的开始簇号。对上面这段代码画出它的简易流程图如下:图5.4.3:5.5 Kernel加载5.5.1主要流程介绍Loader.bin进行加载内核进入保

54、护模式向内核交出控制权图5.5.1图5.5.2图5.5.3图5.5.4第6章系统测试所谓软件测试就是在软件研发和投入市场运行前的各个阶段,对于各个阶层的需求分析,设计规格说明程序编码等过程中阶段和最终性能的检查,它们是软件质量保证的关键。6.1 测试方法和技术(1)黑盒Test黑盒Test我们也把他称为功能测试,他主要用来检测系统的各个功能是否可以使用。因为他测试的过程中,并不分析代码的逻辑结构,所以把他称为黑盒测试。(2)白盒Test白盒测试就是通过测试程序的目标源代码,通常白盒测试的常见方法有,基本的路径测试法,逻辑的覆盖法,静态结构的分析法,代码检查法,路径覆盖的方法。(3)单元Test单元测试是对于程序中最小可测试单元的一种测试方法,对于每种编程语言来说,每一种单元测试的测试单元都不一样。(4)性能Test非功能性测试包括性能检测,负载检测,可靠性检测,兼容性检测以及其他方面,肺功能性测试不能直接进行测试,必须间接的进行测试。而且没有固定的测试标准。6.2 测试设计(1)可以对x86简易操作系统进行单元测试,对于该单元测试,可以是用Bochs Debug来进行测试。(2)可以对x86简易操作系统进行非功能性测试,而非功能性测试主要进行性能测试,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论