怎样自己写操作系统Word文档下载推荐.docx
- 文档编号:18838212
- 上传时间:2023-01-01
- 格式:DOCX
- 页数:20
- 大小:27.03KB
怎样自己写操作系统Word文档下载推荐.docx
《怎样自己写操作系统Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《怎样自己写操作系统Word文档下载推荐.docx(20页珍藏版)》请在冰豆网上搜索。
著名的C编程器。
因为我们需要写一个C程序将自己的OS转移到软盘中。
●一张空软盘:
它用于存储编写的操作系统,也是启动设备。
●一台装有Linux的计算机:
这台机器可以很旧,386、486都可以。
在大部分标准Linux发行版中都会带有as86和ld86。
在我使用的RedHat7.3中就包含有这两个工具,并且在默认的情况下,它已经安装在机器里。
如果使用的Linux没有这两个工具,可以从网上下载(http:
//www.cix.co.uk/~mayday/),这两个工具都包含在一个名为bin86的软件包中。
此外,有关的文档也可以在网上获得(www.linux.org/docs/ldp/howto/Assembly-HOWTO/as86.html)。
开始工作
使用一个你喜欢的编辑器输入以下内容:
entrystart
start:
movax,#0xb800
moves,ax
seges
mov[0],#0x41
mov[1],#0x1f
loop1:
jmploop1
这是as86可以读懂的一段汇编程序。
第一个句子指明了程序的入口点,声明整个过程从start处开始。
第二行指明了start的位置,说明整个程序要从start处开始执行。
0xb800是显存的开始地址。
#表明其后是一个立即数。
执行语句:
movax,#oxb800
ax寄存器的值就变为0xb800,这就是显存的地址。
下面再将这个值移至es寄存器,es是附加段寄存器。
请记住8086有一个分段的体系结构。
它的各段寄存器为代码段、数据段、堆栈段和附加段,对应的寄存器名称分别为cs、ds、ss和es。
事实上,我们把显存地址送入了附加段,因此,任何送入附加段的东西都会被送到显存中。
要在屏幕上显示字符,就需要向显存中写两个字节。
前一个是所要显示字符的ASCⅡ值,第二个字节表示该字符的属性。
属性包括字符的前景色、背景色及是否闪烁等等。
seges指明下一个将要执行的指令是指向es段的。
所以,我们把值0x41(在ASCⅡ中表示的字符是A)送到显存的第一个字节中。
接下来要把字符的属性送到下一个字节当中。
在此输入的是0x1f,该属性指的是在蓝色背景下显示白色的字符。
因此,如果执行这个程序,就可以在屏幕上得到显示在蓝底上的一个白色的A。
接着是一个循环。
因为在执行完显示字符的任务后,要么让程序结束,要么使用一个循环使其永远运行下去。
把该文件命名为boot.s,然后存盘。
此处显存的概念说得不是很清楚,有必要进一步解释一下。
假设屏幕由80列×
25行组成,那么第一行就需要160字节,其中一个字节用于表示字符,另外一个字节用于表示字符的属性。
如果要在第三行显示某一字符的话,就要跳过显存的第0和1字节(它们是用于显示第1列的),第2和3字节(它们是用于显示第2列的),然后把需要显示字符的ASCⅡ码值入第4字节,把字符的属性写入第5字节。
把程序写至启动扇区
下面写一个C程序,把我的操作系统写入软盘第一扇区。
程序内容如下:
#include<
sys/types.h>
/*unistd.h需要这个文件*/
unistd.h>
/*包含有read和write函数*/
fcntl.h>
intmain()
{
charboot_buf[512];
intfloppy_desc,file_desc;
file_desc=open("
./boot"
O_RDONLY);
read(file_desc,boot_buf,510);
close(file_desc);
boot_buf[510]=0x55;
boot_buf[511]=0xaa;
floppy_desc=open("
/dev/fd0"
O_RDWR);
lseek(floppy_desc,0,SEEK_CUR);
write(floppy_desc,boot_buf,512);
close(floppy_desc);
}
首先,以只读模式打开boot文件,然后在打开文件时把文件描述符复制到file_desc变量中。
从文件中读取510个字符,或者读取直到文件结束。
在本例中由于文件很小,所以是读取至文件结束。
然后关闭文件。
最后4行代码打开软盘驱动设备(一般来说是/dev/fd0)。
使用lseek找到文件开始处,然后从缓冲中向软盘写512个字节。
在read、write、open和lseek的帮助页中,可以看到与函数所有有关的参数及其使用方法。
程序中有两行比较难懂:
该信息是用于BIOS的,如果它识别出该设备是一个可启动的设备,那么在第510和511的位置,该值就应该是0x55和0xaa。
程序会把文件boot读至名为boot_buf的缓冲中。
它要求改变第510和第511字节,然后把boot_buf写至软盘之上。
如果执行代码,软盘上的前512字节就包含了启动代码。
最后,把文件存为write.c。
编译运行
使用下面的命令把文件变为可执行文件:
as86boot.s-oboot.o
ld86-dboot.o-oboot
ccwrite.c-owrite
首先将boot.s文件编译成目标文件boot.o,然后将该文件连接成最终的boot文件。
最后C程序编译成可执行的write文件。
插入一个空白软盘,运行以下程序:
./write
重新启动电脑,进行BIOS的界面设置,并且把软盘设为第一个启动的设备。
然后插入软盘,电脑从软盘上启动。
启动完成后,在屏幕上可以看到一个字母A(蓝底白字),启动速度很快,几乎是在瞬间完成。
这就意味着系统已经从我们制作的软盘上启动了,并且执行了刚才写入启动扇区的程序。
现在,它正处在一个无限循环的状态。
所以,如果想进入Linux,必需拿掉软盘,并且重启机器。
至此,这个操作系统就算完成了,虽然它没有实现什么功能,但是它已经可以启动机器了。
下一期我将在这个启动扇区程序里加入一些代码,使它可以做一些比较复杂的事情(比如使用BIOS中断、保护模式切换等等)。
上一期,我讲述了如何在软盘的启动扇区写一些代码,然后再从软盘启动的过程。
制作好一个启动扇区,在切换到保护模式之前,我们还应该知道如何使用BIOS中断。
BIOS中断是一些由BIOS提供的、为了使操作系统的创建更容易的低级程序。
在本文中,我们将学习处理BIOS的中断。
为什么要用BIOS
BIOS会把启动扇区拷贝至RAM中,并且执行这些代码。
除此之外,BIOS还要做很多其它的事情。
当一个操作系统刚开始启动时,系统中并没有显卡驱动、软盘驱动等任何驱动程序。
因此,启动扇区中不可能包含任何一个驱动程序,我们要采取其它的途径。
这个时候,BIOS就可以帮助我们了。
BIOS中包含有各种可以使用的程序,包括检测安装的设备、控制打印机、计算内存大小等用于各种目的的程序。
这些程序就是所说的BIOS中断。
如何调用BIOS中断
在一般的程序设计语言中,函数的调用是一件非常容易的事情。
比如在C语言中,如果有一个名为display的程序,它带有两个参数,其中参数noofchar表示显示的字符数,参数attr表示显示字符的属性。
那么要调用它,只需给出程序的名称即可。
对于中断的调用,我们使用的是汇编语言中的int指令。
比如,在C语言中要显示一些东西时,使用的指令如下所示:
display(nofchar,attr);
而使用BIOS时,要实现相同功能使用的指令如下:
int0x10
如何传递参数
在调用BIOS中断之前,我们需要先往寄存器中送一些特定的值。
假设要使用BIOS的中断13h,该中断的功能是把数据从软盘传送至内存之中。
在调用该中断之前,要先指定拷贝数据的段地址,指定驱动器号、磁道号、扇区号,以及要传送的扇区数等等。
然后,就要往相应的寄存器送入相应的值。
在进行下面的步骤前,读者有必要对这一点有比较明确地认识。
此外,一个比较重要的事实是同一个中断往往可以实现各种不同的功能。
中断所实现的确切功能取决于所选择的功能号,功能号一般都存在ah寄存器之中。
比如中断13h可以用于读磁盘、写磁盘等功能,如果把3送入ah寄存器中,那么中断选择的功能就是写磁盘;
如果把2送入ah寄存器中,选择的功能则是读磁盘等。
这次我们的源代码由两个汇编语言程序和一个C程序组成。
第一个汇编文件是引导扇区的代码。
在引导扇区中,我们写的代码是要把软盘中第二扇区拷贝至内存段的0x500处(地址是0x5000,即偏移地址为0)。
这时我们需要使用BIOS的中断13h。
这时启动扇区的代码就会把控制权转移至0x500处。
在第二个汇编文件中,代码会使用BIOS中断10h在屏幕上显示一个信息。
C程序实现的功能则是把可执行的文件1拷贝至启动扇区,把可执行的文件2拷贝至软盘的第二扇区。
启动扇区代码
使用中断13h,启动扇区把软盘第二扇区里的内容加载至内存的0x5000处(段地址为0x500)。
下面的代码是用于实现这一目的的代码,将其保存至文件sbect.s中。
LOC1=0x500
movax,#LOC1
movbx,#0
movdl,#0
movdh,#0
movch,#0
movcl,#2
moval,#1
movah,#2
int0x13
jmpi0,#LOC1
上面代码第一行类似于一个宏。
接下去的两行则是把值0x500加载至es寄存器中,这是软盘上第二扇区代码将拷贝到的地方(第一扇区是启动扇区)。
这时,把段内的偏移设为0。
接下来把驱动器号送入dl寄存器中,其中磁头号送入dl寄存器中,磁道号送入ch寄存器中,扇区号送入cl寄存器中,扇区数送入al寄存器之中。
我们想要实现的功能是把扇区2、磁道号为0、驱动器号为0的内容送至段地址0x500处。
所有这些参数都和1.44MB的软盘相对应。
把2送入ah寄存器中,是选择了由中断13h提供的相应功能,即实现从软驱转移数据的功能。
最后调用中断13h,并且转至偏移为0的段地址0x500处。
第二个扇区的代码
第二个扇区中的代码如下所示(把这些代码保存至文件sbect2.s之中):
movah,#0x03
xorbh,bh
movcx,#26
movbx,#0x0007
movbp,#mymsg
movax,#0x1301
mymsg:
.byte13,10
.ascii“OperatingSystemisLoading......”
上面代码将被加载至段地址为0x500处,并且被执行。
在这段代码中,使用了中断10h来获取目前的光标位置,然后显示信息。
从第3行到第5行用于得到目前光标的位置,在此中断10h选用的是功能3。
然后,清除了bh寄存器的内容,并把字符串送至ch寄存器中。
在bx中,我们送入了页码及显示的属性。
此处,我们想要在黑背景上显示白色的字符。
然后,把要显示字符的地址送到bp之中,信息由两个字节组成,其值分别为13的10,它们分别对应回车和LF(换行)的ASCⅡ值。
接下来是一个由29个字符组成的串;
在下面实现的功能是输出字符串然后移动光标;
最后是调用中断,然后进入循环。
C程序代码
C程序的源代码如下所示,将其存储为write.c文件。
#include/*unistd.hneedsthis*/
#include/*containsread/write*/
#include
file_desc=open(“./bsect”,O_RDONLY);
floppy_desc=open(“/dev/fd0”,O_RDWR);
lseek(floppy_desc,0,SEEK_SET);
file_desc=open(“./sect2”,O_RDONLY);
read(file_desc,boot_buf,512);
lseek(floppy_desc,512,SEEK_SET);
在上一期中,我曾经介绍过如何操作能启动的软盘。
现在这一个过程稍微有点不同,首先把由bsect.s编译出来的可执行文件bsect拷贝至软盘的启动扇区。
然后再把由sect2.s产生的可执行文件sect2拷贝至软盘的第二个扇区。
把上述文件置于同一目录之下,然后分别对其进行编译,方法如下所示:
as86bsect.s-obsect.o
ld86-dbsect.o-obsect
对sect2.s文件重复以上的操作,得出可执行文件sect2。
编译write.c,插入软盘后执行write文件,命令如下所示:
下一步我们要做的事情
从软盘启动以后,可以看到显示出来的字符串。
这是使用了BIOS中断来完成的。
下一期要做的事情是在这个操作系统中实现实模式向保护模式的转换.
在上两期中(自己动手写操作系统1,2),我向大家讲述了如何使用Linux提供的开发工具在软盘的启动扇区写一些代码,以及如何调用BIOS的问题。
现在,这个操作系统已经越来越接近当年LinusTorvalds的那个具有“历史意义”的Linux内核了。
因此,要马上把这个系统切换到保护模式之下。
什么是保护模式
自从1969年推出第一个微处理器以来,Intel处理器就在不断地更新换代,从8086、8088、80286,到80386、80486、奔腾、奔腾Ⅱ、奔腾4等,其体系结构也在不断变化。
80386以后,提供了一些新的功能,弥补了8086的一些缺陷。
这其中包括内存保护、多任务及使用640KB以上的内存等,并仍然保持和8086家族的兼容性。
也就是说80386仍然具备了8086和80286的所有功能,但是在功能上有了很大的增强。
早期的处理器是工作在实模式之下的,80286以后引入了保护模式,而在80386以后保护模式又进行了很大的改进。
在80386中,保护模式为程序员提供了更好的保护,提供了更多的内存。
事实上,保护模式的目的不是为了保护程序,而是要保护程序以外的所有程序(包括操作系统)。
简言之,保护模式是处理器的一种最自然的模式。
在这种模式下,处理器的所有指令及体系结构的所有特色都是可用的,并且能够达到最高的性能。
保护模式和实模式
从表面上看,保护模式和实模式并没有太大的区别,二者都使用了内存段、中断和设备驱动来处理硬件,但二者有很多不同之处。
我们知道,在实模式中内存被划分成段,每个段的大小为64KB,而这样的段地址可以用16位来表示。
内存段的处理是通过和段寄存器相关联的内部机制来处理的,这些段寄存器(CS、DS、SS和ES)的内容形成了物理地址的一部分。
具体来说,最终的物理地址是由16位的段地址和16位的段内偏移地址组成的。
用公式表示为:
物理地址=左移4位的段地址+偏移地址。
在保护模式下,段是通过一系列被称之为“描述符表”的表所定义的。
段寄存器存储的是指向这些表的指针。
用于定义内存段的表有两种:
全局描述符表(GDT)和局部描述符表(LDT)。
GDT是一个段描述符数组,其中包含所有应用程序都可以使用的基本描述符。
在实模式中,段长是固定的(为64KB),而在保护模式中,段长是可变的,其最大可达4GB。
LDT也是段描述符的一个数组。
与GDT不同,LDT是一个段,其中存放的是局部的、不需要全局共享的段描述符。
每一个操作系统都必须定义一个GDT,而每一个正在运行的任务都会有一个相应的LDT。
每一个描述符的长度是8个字节,格式如图3所示。
当段寄存器被加载的时候,段基地址就会从相应的表入口获得。
描述符的内容会被存储在一个程序员不可见的影像寄存器(shadowregister)之中,以便下一次同一个段可以使用该信息而不用每次都到表中提取。
物理地址由16位或者32位的偏移加上影像寄存器中的基址组成。
实模式和保护模式的不同可以从图1和图2中很清楚地看出来。
图1实模式的寻址
图2保护模式下的寻址
图3段描述俯的格式
此外,还有一个中断描述符表(IDT)。
这些中断描述符会告诉处理器到那里可以找到中断处理程序。
和实模式一样,每一个中断都有一个入口,但是这些入口的格式却完全不同。
因为在切换到保护模式的过程中没有使用到IDT,所以在此就不多做介绍了。
进入保护模式
80386有4个32位控制寄存器,名字分别为CR0、CR1、CR2和CR3。
CR1是保留在未来处理器中使用的,在80386中没有定义。
CR0包含系统的控制标志,用于控制处理器的操作模式和状态。
CR2和CR3是用于控制分页机制的。
在此,我们关注的是CR0寄存器的PE位控制,它负责实模式和保护模式之间的切换。
当PE=1时,说明处理器运行于保护模式之下,其采用的段机制和前面所述的相应内容对应。
如果PE=0,那么处理器就工作在实模式之下。
切换到保护模式,实际就是把PE位置为1。
为了把系统切换到保护模式,还要做一些其它的事情。
程序必须要对系统的段寄存器和控制寄存器进行初始化。
把PE位置1后,还要执行跳转指令。
过程简述如下:
1.创建GDT表;
2.通过置PE位为1进入保护模式;
3.执行跳转以清除在实模式下读取的任何指令。
下面使用代码来实现这个切换过程。
需要的东西
◆一张空白软盘
◆NASM编译器
下面是整个程序的源代码:
org0x07c00;
起始地址是0000:
7c00
jmpshortbegin_boot;
跳过其它的数据,跳转到引导程序的开始处
bootmesgdb"
OurOSbootsectorloading......"
pm_mesgdb"
Switchingtoprotectedmode...."
dw512;
每一扇区的字节数
db1;
每一簇的扇区数
dw1;
保留的扇区号
db2
dw0x00e0
dw0x0b40
db0x0f0
dw9
dw18
dw2;
读写扇区号
dw0;
隐藏扇区号
print_mesg:
movah,0x13;
使用中断10h的功能13,在屏幕上写一个字符串
moval,0x00;
决定调用函数后光标所处的位置
movbx,0x0007;
设置显示属性
movcx,0x20;
在此字符串长度为32
movdx,0x0000;
光标的起始行和列
int0x10;
调用BIOS的中断10h
ret;
返回调用程序
get_key:
movah,0x00
int0x16;
Get_key使用中断16h的功能0,读取下一个字符
ret
clrscr:
movax,0x0600;
使用中断10h的功能6,实现卷屏,如果al=0则清屏
movcx,0x0000;
清屏
movdx,0x174f;
卷屏至23,79
movbh,0;
使用颜色0来填充
调用10h中断
begin_boot:
callclrscr;
先清屏
movbp,bootmesg;
提供串地址
callprint_mesg;
输出信息
callget_key;
等待用户按下任一键
bits16
movax,0xb800;
使gs指向显示内存
movgs,ax;
在实模式下显示一个棕色的A
movword[gs:
0],0x641;
显示
调用Get_key等待用户按下任一键
movbp,pm_mesg;
设置串指针
调用print_mesg子程序
等待按键
cl
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 怎样 自己 操作系统