您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 商业计划书 > 怎样写一个简单的操作系统
怎样写一个简单的操作系统?(原文标题:Howtowriteasimpleoperatingsystem)收藏怎样写一个简单的操作系统?翻译:magictong(童磊)2011年1月版权:MikeSaunders和MikeOS的全体开发2009年原文地址:很简单的一篇关于操作系统编写的入门文章,本身可能没什么特别深的技术含量,但是不失为一个继续研究的起点,当时随意浏览了一下,觉得还不错,就决定把它翻译出来,欢迎大牛批评和斧正,可能有一些翻译错误,也希望不吝赐教。——magictong2010.01.26晨目录简介必备知识计算机启动汇编入门第一个操作系统进阶简介本文主要介绍怎样编写和构建您的第一个,基于x86汇编语言的操作系统。它解释了计算机开机的基本过程,一些基本的汇编语言,以及怎样进一步提升自己这方面的技术。最终编写的操作系统将是非常小的一个程序(仅仅是一个系统引导程序),并且只有非常少的功能,但它是您在这方面进一步进行研究和探索的一个起点。在您阅读了本文之后,如果您想更进一步在这方面进行探索并扩展您的能力,您可以继续看一下MikeOS(译注:)项目,这是一个更大更完备的x86汇编语言操作系统。必备知识编程经验是必不可少的。如果你已经使用一些高级语言像PHP和JAVA之类的做过一些开发,那再好不过,但是,你最好还要具备一些更底层语言的知识,像C之类的,特别是对一些内存和指针的问题比较熟悉。在本文中,我们将使用Linux操作系统来作开发平台,当然,在Windows上面进行操作系统开发也是可以是的,但是显然在Linux上面开发更加的简单,因为你需要点击几下鼠标敲击几个命令就可以获得一套完整的开发工具。在Linux上面制作软盘和CD–ROM也更方便,你不需要安装一些繁琐的驱动程序。现在安装Linux是非常容易的,如果你不想在你的计算机上面安装双系统,你可以把Ubuntu(译注:Ubuntu是Linux操作系统中的一个)安装在VMware或者VirtualBox上面,进入Ubuntu之后,只需要在命令行窗口键入下面的命令,就可以获得本文所需要的全部工具,简单把:sudoapt-getinstallbuild-essentialqemunasm通过这个命令你可以获得开发工具(编译器等等),QEMUPC仿真器和NASM的汇编器等等,汇编器能把汇编语言转换原生的机器码而组成可执行文件。计算机启动如果你正在为一个x86系统(这是最好的选择,因为有大量的文档可以参考)的计算机写操作系统,你需要理解计算机启动过程的基本知识,不过幸运的是,你现在不需要去了解图形驱动程序和网络协议等等复杂的部分,因此你可以专注于最本质的地方。当计算机通电之后,它最开始执行的是BIOS(基本输入/输出系统)程序,它本质上是一个内置在系统中的微型操作系统。BIOS执行一些基本的硬件检测(如内存检查等),并且绘制一些特殊的图形(如DELL的LOGO)或者打印一些诊断文本到屏幕上。做完这些之后,它开始从某个可以找到的媒介上加载你的操作系统。然后大部分的计算机会跳转到硬盘驱动器并开始执行主引导区(MBR)的代码,主引导区是指一个硬盘驱动器最开始的512个字节的部分。有些计算机会尝试在一个软盘(启动扇区)或者CD–ROM上找到可执行代码。计算机具体会去哪里寻找引导程序,依赖于引导顺序-你可以在BIOS的选项屏幕上明确的指定它。BIOS从选中的媒介(译注:硬盘,软盘,CD-ROM)中加载512字节到内存中,然后开始执行它。这就是(传说中的)引导程序,这个小程序然后加载操作系统内核或一个更大一些的引导程序(例如,Linux系统下的GRUB/LILO)。为了告诉操作系统它是一个引导扇区,512字节的引导程序在最后面有两个特殊的数字作标记,我们稍后将介绍它。在计算机启动、引导的时候,有一个有趣的地方。在以前,基本上所有的计算机都配有一个软盘驱动器,因此BIOS配置的是从软盘驱动器启动,然而,现在的大部分的个人电脑都没有软盘驱动器,而是配备了一个CD–ROM,为了满足这种需要,专门开发了一个hack(译注:ahack直译不知道怎么翻译,大概就是类似外挂一样的意思,干预引导程序,呵呵)程序。当计算机从CD-ROM启动的时候,它可以模拟一个软盘出来,BIOS将从CD–ROM驱动器上面读取一个数据块并加载,然后执行它,就好像它是一个软盘一样。这对于操作系统开发者来说是非常(译注:原文用了incredibly,表示非常非常有用的,呃)有用的,因为我们可以只制作一个引导我们的操作系统的软盘,但是依然可以引导只有CD–ROM设备的机器。(相对来说,软盘是比较容易使用和操作的,而CD-ROM的文件系统则显然要复杂得多)。因此总的来说,启动过程如下:1、打开电源,计算机启动然后开始执行BIOS代码。2、BIOS程序寻找软盘或硬盘驱动器等多种媒介(译注:可以在BIOS中设定寻找顺序)。3、BIOS将从指定的媒介中加载512字节的引导扇区,然后开始执行它。4、引导扇区然后再去加载操作系统本身,或者更加复杂的引导程序。对于MikeOS,我们写了一个512字节的引导程序,并将它制作成一个软盘映像文件(虚拟软盘)。对于只有CD–ROM的驱动器,我们可以把该映像文件拷贝到CD上。不过无论使用哪种方式,BIOS都将正常加载它,就好像它是一个软盘一样,并开始执行它。之后我们就可以控制整个系统了!汇编入门现代操作系统大部分都是使用C或者C++编写,因为这对于可移植性和代码维护来说是至关重要的,但是这不是免费的午餐,在处理上就增加了一个更加复杂的层次。编写您的第一个操作系统,建议您最好是使用汇编语言,在MikeOS中也是使用的汇编语言,虽然汇编语言显得冗余和不可移植,但是您不用去担心编译器和链接器,这是它的优点。另外,此外,你需要一点汇编代码去启动任何操作系统。汇编语言(或俗称的“汇编”)是表示CPU执行指令的一种文本化方式。例如,一条表示在CPU中移动数据的指令用二进制表示可能1100100101101110,这种表示方法非常令人难以记忆(译注:简直是发狂的)。汇编语言使用一些助记符,如movax,30来代替这些指令。汇编指令直接与机器码CPU指令相关联,我们就不用再关心那些看起来毫无意义的二进制数字。跟大多数的编程语言一样,汇编语言也是有序的指令流。你可以在不同的指令位置进行跳转,也可以设置子程序或者函数,但是它比C#之类的程序要小得多。使用汇编,你无法给出一个打印“HelloWorld”到屏幕的指令,因为CPU根本没有屏幕这样一个概念!相反,你可以直接操作内存,控制RAM(译注:随机存取存储器),在它们上面进行算术运算并把结果放到正确的位置。听起来很疯狂么?但是汇编并不是很难掌握,虽然在一开始你会觉得有点陌生和不可理解。在汇编语言层次,并没有高级语言中类似变量这样的一些抽象的概念。你所能做的就是设置Registers(译注:寄存器)的值,Registers是内置在CPU中的高速存储设备。你可以把数据存放在Registers上面并且执行计算。在16位模式下,这些寄存器只可以存储0到65535之间的数字。下面是一个典型的X86CPU的基本寄存器列表:AX,BX,CX,DX通用数据寄存器,可以用于存储正在使用的数据。譬如,你可以使用AX存储键盘上刚刚按下的字符;使用CX作为一个循环计数器。(注:16位寄存器可以被分割为8位寄存器使用,比如,AH/AL,BH/BL等等)SI,DI源操作数和目的操作数寄存器。用于指向内存中的某个地址来获取和存储数据。SP堆栈寄存器(稍后再解释)。IP(sometimesCP)指令寄存器,存放着即将要执行的下一条指令的内存地址,当一条指令执行结束后,指令寄存器进行自增(译注:不是增加1,而应该是自增下一条指令的长度)以便于指向接下来的指令地址。你可以改变指令寄存器的内容使得代码逻辑跳转执行(译注:一般不能直接改动,而是通过call和ret之类的指令间接改动)。(译注:32位系统寄存器的位数增加到32位,相应的名称叫EAX,EBX,ECX,EDX等等)因此你可以像使用变量一样用这些寄存器来存储数据,只不过它们在数据大小和用途上比较固定。有一类比较特殊的寄存器,叫做段寄存器,这主要是因为旧的计算机系统的限制,内存的处理被限制在一个64K的叫做段的块上。这是一个非常麻烦而混乱的问题,不过幸运的是,你现在不用担心,因为目前你即将编写操作系统远远小于一千字节,在MikeOS里面,我们把程序局限在一个64K的段里面,这样我们就不必去招惹麻烦的段寄存器了。堆栈是从主存储器上面专门开辟的一块区域,用来存储临时信息。之所以叫着栈是因为一个数字堆积在另一个数字是上面,很形象的一种称呼。你可以想象一下,如果你有一个品客(译注:国际著名薯片品牌)的包装筒,如果你往里面顺序放入一张扑克牌,一个iPodShuffle和一个啤酒杯垫子,那么你再把它们拿出来的时候就是完全相反的顺序了(先是啤酒杯垫子,然后是ipodshuffle,最后是扑克牌)。这跟数字也是一样的,如果你把数字5,7和15顺序压入堆栈,那么你弹出这些数字的时候顺序就刚好相反了,先是数字15,然后是数字7,最后是15。在汇编里面,你可以把寄存器的值压到堆栈上,处理完某些事情后在把它们从堆栈上弹回到寄存器中,这个主要用于当你想使用某些寄存器去干别的事情的时候,而你又不想破坏现在寄存器里面的值,那么你可以把寄存器里面的值压入堆栈,等处理完其他事情后再从堆栈上把值弹回寄存器中。计算机的内存可以看作一个线性的空间,就像一个个连续的鸽子笼一样,它的范围从0开始直到你所安装的内存的最大值(现代计算机的内存高达数百万字节)。例如,你可能怎在使用浏览器来查看内存中53634246字节的一个文档文件,但是我们人类的计数是基于10的幂的(10,100,1000等等,也就是十进制),而计算机计数则是基于2的幂的(因为计算机使用2进制更好)。为了能更好的描述数字,我们使用16(基于16的幂)进制,可以对照下面的表格来理解:10进制0123456789101112131415161718192016进制0123456789ABCDEF1011121314如图中表格所示,我们平时都是使用的十进制计数系统,用0-9计数,十六进制计数系统使用0-F进行计数,对于没有接触过进制的人来说,可能有点困惑,不过没关系,很快你就能学会它。在汇编语言里面,我们通过在数字字符后面加上‘h’表示一个十六进制的数字,比如0Ah就表示十进制的10(你也可以通过加一个0x前缀的方式来表示十六进制,例如0x0A)。让我们先来看看几条常用的汇编指令,主要是数据传送指令,比较指令和数学计算指令等等,它们将是构建你的操作系统的基石。总共大概有数百条汇编指令,不过你不需要全部记住它们,熟悉常用指令就可以了,因为90%的时间我们都是在使用其中的极少数指令。mov数据传送指令,从寄存器或者内存中移动数据到另一个地方。例如:movax,30表示把数据30传送到寄存器ax中。要获取内存中的数据,如果它被某个寄存器指向,你可以使用方括号。例如,如果bx中的数据是80,那么movax,[bx]的意思就是,获取内存地址为80的处的数据,并把它传送到ax寄存器中。你也可以使用这条指令在两个寄存器之间传送数据,譬如:movbx,cx。add/sub数据加减指令,addax,FFh表示加上一个FFh(十六进制数,表示十进制的255)到ax寄存器中,sub指令的使用也是一样的,subdx,50。cmp比较指令。用来比较一个寄存器和一个数字,例如,cmpcx,12的意思是将cx中的数据和12进行比较。根据比较的结果,更新CPU的标志寄存器(译注:标志寄存器是用来存储最后一次运算结果的状态的特殊寄存器)。在这个例子里面,如果12大于cx中存储的值,比较结果是一个负数,那么标志寄存器的
本文标题:怎样写一个简单的操作系统
链接地址:https://www.777doc.com/doc-4818491 .html