《若何编写操作系统.docx》由会员分享,可在线阅读,更多相关《若何编写操作系统.docx(11页珍藏版)》请在优知文库上搜索。
1、若何编写自己的操作系统有人可能担忧自己既没有学过计算机原理,也没有学过操作系统原理,更不懂汇编语言,对C语言也一知半解,能写操作系统吗答案是没问题。我将带大家一步一步完成自己的操作系统。当然如果学一学上述内容再好不过。首先要明确处理器(也就是CPU)控制着计算机。对PC而言,启动的时候,CPU都处在实模式状态,相当于只是一个Intel8086处理器。也就是说,即使你现在拥有一个奔腾处理器,它的功能也只能是8086级别。从这一点上来讲,可以使用一些软件把处理器转换到著名的保护模式。只有这样,我们才可以充分利用处理器的强大功能。编写操作系统开场是对BIOS控制,取出存储在ROM里的程序。BIOS是
2、用来执行POST(PowerOnSelfTest,自检)的。自检是检查计算机的完整性(比方外设是否工作正常、键盘是否连接等)。这一切完成以后,你就会听到PC喇叭发出一声清脆的响声。如果一切正常,BloS就会选择一个启动设备,并且读取该设备的第一扇区(即启动扇区),然后控制过程就会转移到指定位置。启动设备可能是一个软盘、光盘、硬盘,或者其它所选择的设备。在此我们把软盘作为启动设备。如果我们已经在软盘的启动扇区里写了一些代码,这时它就被执行。因此,我们的目的很明确,就是往软盘的启动扇区写一些程序。首先使用8086汇编来写一个小程序,然后将其拷贝至软盘的启动扇区。为了实现拷贝,要写一个C程序。最后,
3、使用软盘启动计算机。需要的工具 as86:这是一个汇编程序,它负责把写的代码转换成目标文件。 ld86:这是一个连接器,as86产生的目标代码由它来转换成真正的机器语言。机器语言是8086能够解读的形式。 GCC:著名的C编程器。因为我们需要写一个C程序将自己的OS转移到软盘中。 一张空软盘:它用于存储编写的操作系统,也是启动设备。 一台装有LinUX的计算机:这台机器可以很旧,386、486都可以。在大局部标准Linux发行版中都会带有as86和ld86.在我使用的RedHat73中就包含有这两个工具,并且在默认的情况下,它已经安装在机器里。如果使用的LinUX没有这两个工具,可以从网上下载
4、(:/cix.co.uk/mayday/),这两个工具都包含在一个名为bin86的软件包中。此外,有关的文档也可以在网上获得(linux.orgdocsldphowtoAssembly-HOWTOas86.html)o开场工作使用一个你喜欢的编辑器输入以下内容:entrystartstart:movax,#Oxb8OOmoves,axsegesmov0,#0x41segesmovl,#OxlfIoopkjmpIoopl这是as86可以读懂的一段汇编程序。第一个句子指明了程序的入口点,声明整个过程从Start处开场。第二行指明了start的位置,说明整个程序要从start处开场执行。0xb800
5、是显存的开场地址。#说明其后是一个立即数。执行语句:movax,#oxb800ax存放器的值就变为0xb800,这就是显存的地址。下面再将这个值移至es存放器,es是附加段存放器。请记住8086有一个分段的体系构造。它的各段存放器为代码段、数据段、堆栈段和附加段,对应的存放器名称分别为cs、ds、SS和es。事实上,我们把显存地址送入了附加段,因此,任何送入附加段的东西都会被送到显存中。要在屏幕上显示字符,就需要向显存中写两个字节。前一个是所要显示字符的ASeIl值,第二个字节表示该字符的属性。属性包括字符的前风光、背风光及是否闪烁等等。SegeS指明下一个将要执行的指令是指向es段的。所以,
6、我们把值0x41(在ASCn中表示的字符是A)送到显存的第一个字节中。接下来要把字符的属性送到下一个字节当中。在此输入的是OXlf,该属性指的是在蓝色背景下显示白色的字符。因此,如果执行这个程序,就可以在屏幕上得到显示在蓝底上的一个白色的Ao接着是一个循环。因为在执行完显示字符的任务后,要么让程序完毕,要么使用一个循环使其永远运行下去。把该文件命名为boots然后存盘。2若何编写自己的操作系统此处显存的概念说得不是很清楚,有必要进一步解释一下。假设屏幕由80列X25行组成,那么第一行就需要160字节,其中一个字节用于表示字符,另外一个字节用于表示字符的属性。如果要在第三行显示某一字符的话,就要
7、跳过显存的第。和1字节(它们是用于显示第1列的),第2和3字节(它们是用于显示第2列的),然后把需要显示字符的ASCIl码值入第4字节,把字符的属性写入第5字节。把程序写至启动扇区下面写一个C程序,把我的操作系统写入软盘第一扇区。程序内容如下:#include*unistd.h需要这个文件*/#include/*包含有read和write函数*/#includeintmain()charboot-buf512;intfloppy_desc,file_desc;file_desc=open(,.boot,O_RDONLY);read(file_desc,boot_buf,510);close(f
8、ile_desc);boot_buf510=0x55;boot_buf511=Oxaa;floppy_desc=open(,7devfd0,0_RDWR);lseek(floppy_desc,0,SEEK_CUR);Write(floppy_desc,boot_buf,512);close(floppy_desc);)首先,以只读模式翻开boot文件,然后在翻开文件时把文件描述符复制到file_desc变量中。从文件中读取510个字符,或者读取直到文件完毕。在本例中由于文件很小,所以是读取至文件完毕。然后关闭文件。最后4行代码翻开软盘驱动设备(一般来说是devfd)使用Iseek找到文件开场处
9、,然后从缓冲中向软盘写512个字节。在read、write.OPen和ISeek的帮助页中,可以看到与函数所有有关的参数及其使用方法。程序中有两行比较难懂:boot_buf510=0x55;boot_buf511=Oxaa;该信息是用于BloS的,如果它识别出该设备是一个可启动的设备,那么在第510和511的位置,该值就应该是0x55和Oxaa0程序会把文件boot读至名为boot_buf的缓冲中。它要求改变第510和第511字节,然后把boojbuf写至软盘之上。如果执行代码,软盘上的前512字节就包含了启动代码。最后,把文件存为Write.c。编译运行使用下面的命令把文件变为可执行文件:a
10、s86boot.s-oboot.oId86-dboot.o-obootccwrite.c-owrite首先将boot.s文件编译成目标文件boot.o,然后将该文件连接成最终的boot文件。最后C程序编译成可执行的write文件。插入一个空白软盘,运行以下程序:./write重新启动电脑,进展BIOS的界面设置,并且把软盘设为第一个启动的设备。然后插入软盘,电脑从软盘上启动。启动完成后,在屏幕上可以看到一个字母A(蓝底白字),启动速度很快,几乎是在瞬间完成。这就意味着系统已经从我们制作的软盘上启动了,并且执行了刚刚写入启动扇区的程序。现在,它正处在一个无限循环的状态。所以,如果想进入LinUX
11、,必需拿掉软盘,并且重启机器。至此,这个操作系统就算完成了,虽然它没有实现什么功能,但是它己经可以启动机器了。下一期我将在这个启动扇区程序里参加一些代码,使它可以做一些比较复杂的事情(比方使用BK)S中断、保护模式切换等等)。自己动手写操作系统(二)伊梅上一期,我讲述了若何在软盘的启动扇区写一些代码,然后再从软盘启动的过程。制作好一个启动扇区,在切换到保护模式之前,我们还应该知道若何使用BloS中断。BloS中断是一些由BloS提供的、为了使操作系统的创立更容易的低级程序。在本文中,我们将学习处理BIoS的中断。为什么要用BIOSBIOS会把启动扇区拷贝至RAM中,并且执行这些代码。除此之外,
12、BIOS还要做很多其它的事情。当一个操作系统刚开场启动时,系统中并没有显卡驱动、软盘驱动等任何驱动程序。因此,启动扇区中不可能包含任何一个驱动程序,我们要采取其它的途径。这个时候,BloS就可以帮助我们了。BlOS中包含有各种可以使用的程序,包括检测安装的设备、控制打印机、计算内存大小等用于各种目的的程序。这些程序就是所说的BIOS中断。3若何编写自己的操作系统若何调用BIOS中断在一般的程序设计语言中,函数的调用是一件非常容易的事情。比方在C语言中,如果有一个名为display的程序,它带有两个参数,其中参数noofchar表示显示的字符数,参数attr表示显示字符的属性。那么要调用它,只需
13、给出程序的名称即可。对于中断的调用,我们使用的是汇编语言中的int指令。比方,在C语言中要显示一些东西时,使用的指令如下所示:display(nofchar,attr);而使用BIOS时,要实现一样功能使用的指令如下:intOxlO若何传递参数在调用BloS中断之前,我们需要先往存放器中送一些特定的值。假设要使用BIOS的中断13h,该中断的功能是把数据从软盘传送至内存之中。在调用该中断之前,要先指定拷贝数据的段地址,指定驱动器号、磁道号、扇区号,以及要传送的扇区数等等。然后,就要往相应的存放器送入相应的值。在进展下面的步骤前,读者有必要对这一点有比较明确地认识。此外,一个比较重要的事实是同一
14、个中断往往可以实现各种不同的功能。中断所实现确实切功能取决于所选择的功能号,功能号一般都存在ah存放器之中。比方中断13h可以用于读磁盘、写磁盘等功能,如果把3送入ah存放器中,那么中断选择的功能就是写磁盘;如果把2送入ah存放器中,选择的功能那么是读磁盘等。我们要做的事情这次我们的源代码由两个汇编语言程序和一个C程序组成。第一个汇编文件是引导扇区的代码。在引导扇区中,我们写的代码是要把软盘中第二扇区拷贝至内存段的0x500处(地址是0x5000,即偏移地址为0)。这时我们需要使用BloS的中断13h。这时启动扇区的代码就会把控制权转移至0x500处。在第二个汇编文件中,代码会使用BIOS中断
15、IOh在屏幕上显示一个信息。C程序实现的功能那么是把可执行的文件1拷贝至启动扇区,把可执行的文件2拷贝至软盘的第二扇区。启动扇区代码使用中断13h,启动扇区把软盘第二扇区里的内容加载至内存的0x5000处(段地址为0x500)。下面的代码是用于实现这一目的的代码,将其保存至文件sbect.s中。1.OC1=0x500entrystartstart:movax,#LOClmoves,axmovbx,#Omovdl,#0movdh,#Omovch,#Omovcl,#2moval,#lmovah,#2int0x13jmpi0,#LOC1上面代码第一行类似于一个宏。接下去的两行那么是把值0x500加载至es存放器中,这是软盘上第二扇区代码将拷贝到的地方(第一扇区是启动扇区)。这时,把段内的偏移设为Oo接下来把驱动器号送入di存放器中,其中磁头号送入dl存放器中,磁道号送入ch存放器中,扇区号送入cl存放器中,扇区数送入al存放器之中。我们想要实现的功能是把扇区2、磁道号为0、驱动器号为0的内容送至段地址0x500处。所有这些参数都和1.44MB的软盘相对应把2送入ah存放器中,是选择了由中断13h提供的相应功能,即实现从软驱