设为首页收藏本站language 语言切换
查看: 1617|回复: 0
收起左侧

[分享] 从零学写操作系统一

[复制链接]
发表于 2012-6-1 14:20:53 | 显示全部楼层 |阅读模式
拥有一个自己的操作系统和成为无所不能的黑客是每一个计算机爱好者的梦想.
  然而,我们的目的不是写一个自己来用的操作系统,我们的真正目的只是要学习,在写一个真正能运行起来的操作系统过程中,我们会接触到许多平时接触不到的知识.这绝对不会像一个只做数据库开发人员那样,只需要组合语言的能力,数据结构,数据关系处理,用户需求分析等.在写系统时,这些完全用不上.尽管我们并不是想像Linus那样写一个影响世界开发人员的系统,我们的需求会很小,但是这一点的需求,会花上我们大量的时间.而得到的会更多.
  于渊的<<自己动手写操作系统>>就是这样一本书,我现在只看了前两章(只有前两章的电子书),而第二章是一整章的虚拟机使用说明.正是看了它的书,才到网上找到了许多操作系统的代码.插一点其它话题,在网上见到一些人骂他的书不够好,我就不明白,世界上为什么老是有这么多吃的太饱的人?我相信你水平比他高--那你来写一本啊.你水平比他高但你能写的比他好吗?中国人就是这样,总以为自己比别人厉害,看到梁肇新出书也要上去骂一通.我奉劝这种人,请回头看看你自己,你用什么来骂别人.有本事的请你把自己的知识写出来.中国有水平的人不少,但是想写出来的,能写出来的和愿意写出来的就不多了.
  要写一个操作系统,首先要写一个引导程序,这就要求如下基础:
1.了解计算机的启动过程.
2.明白硬盘的分区及其结构.
3.知道CPU,内存的工作方式
4.至少会一种汇编语言.
5.安装一个虚拟机.
  我一向是按需学习的.就是说:用到哪一部分学哪一部分,哪一部分不会就查找哪一部分.暂时看不明白的,或是用不上的统统跳过去.只学习我感兴趣的.
  计算机的启动过程我们只需要了解一点.Bios加电自检,通过之后他就要寻找一个继承它控制权的设备,这个设备可以是软盘,光盘或硬盘.当然,这个查找的顺序是按Biso设置里来的.它的寻找方式是,定位到这种存储器的最前面的第510字节处,读取第511和512两个字节,看一下是不是"55AA"如果是,那么它就将这前面的所有数据读取到内存的07C00h处,并从此处执行.....
  硬盘的结构及分区,由于现在的主流系统是Windows,所以分区基本上以Fat和Ntfs为主,这里要说的是分区的相关知识是系统的知识,即Windows系统或Linux系统的知识,我们如果要写一个成熟操作系统的话,那我们完全可以定义一种自己的分区格式,这里要说明一下网的一些错误观点,因为<<自己动手写操作系统>>中关于引导程序有一句"少于512B的执行码",一些网友认为这是错误的.因为在MBR后面,结束语"55AA"前面还应该有64字节的分区表(DPT).其实网友才是错误的.这本书的作者写的不严谨,正确的说法应该是"小于511B的执行数据".因为"55AA"是512字节的最后两字节,所以前面最多只能有510字节,而网友所说的"DPT"这是Windows系统的分区格式,有些系统为兼容Windows所以才按此来写的.本段开头说过,我们新写一个操作系统完全可以自己定义分区格式,如果运行在软盘或小磁盘中,我们完全可以不定义分区格式,这样,我们的系统将不可以与Widnows共存,当然,即使做为第二块硬盘,Windows也是无法认出此数据的(这也是为什么Windows读不出Linux的Ext2文件).Windows的详细分区格式可以看一下数据恢复网的几篇文件(http://www.sjhf.net/)对Fat12,Fat16,Fat32都有详细的说明.
  CPU与内存的工作方式,这里只需要基础的知识,只要懂汇编就可以了
  写操作系统基本上没有用Masm的,有用as86的(网上有一份关于用as86和gcc写操作系统的三篇文章),有用Fasm的(MenuetOs),还有的用Tasm(FreeDos),但大多都是用Nasm来写的,因为它是跨Windows与Linux并开放源代码的.网上有Nasm的中文文档资料(http://www.pop417.com/bbs/dispbbs.asp?boardid=39&id=840)
  安装一个虚拟机,这是测试一个操作系统最简单的方式.这里用的是Virtual PC.它所虚拟的硬盘文件(VHD)文件就直接是以硬盘格式为标准的.所以你可以将生成的引导程序用十六进制编辑软件直接写到VHD文件的最前面.然后在虚拟机中就可以运行它.Virtual PC生成的软盘文件也是一样.
  下面详细分析一下这段引导代码:
org 07c00h
mov ax,cs
mov ds,ax
mov es,ax
call dispstr
jmp $
dispstr:
mov ax,bootmessage
mov bp,ax
mov cx,16
mov ax,01301h
mov bx,000ch
mov dl,0
int 10h
ret
bootmessage: db "Hello,OS world!"
times 510-($-$$) db 0
dw 0xaa55
org 07c00h,由于Bios会将此段数据加载到07c00h处,所以我们告诉编译器程序要从此处运行.
mov ax,cs
mov ds,ax
mov es,ax
由于引导程序只有512字节,所以将cs,ds统一到一个地址,这个地址实际上就是0,所以我们还可以如此写:
xor ax,ax
mov ds,ax
mov es,ax
至于es,是后面要用到的.call dispstr是子程序调用,与masm是相同的,跳转到dispstr:标签处继续执行.
jmp $.这一句与Win32程序开发中的While消息处理语句不同,这是一个真正的死循环.$表示当前地址,所以它不停的跳到当前地址-无限死循环,直到强行关机或重启
在解释下面的语句之前我们要先了解一下中断,我们可以将中断看成是Windows中的API,只不过它的执行者不是Windows而是BIOS.中断的名称是立即数,调用指令为int.即:
int imm
imm表示立即数.不同的数字表示调用不同的功能.
我们调用API时,都需要知道它的函数原型,同样,使用中断时,我们也要知道它的调用方法,你可以看做它的原型.它的参数就是各个寄存器.
下面来看一下,int 10h的调用方法:
ah,表示调用的功能号,每一个中断又分为几种不同的功能,就是通过ah来区别的.这里我们说明的是int 10h的13号功能,它的作用是在Teletype模式下显示字符串.我们先不必要管它是什么模式,只要知道它是在显示器上写字的就可以了.其它寄存器作用如下:
Al=输出方式
0——字符串中只含显示字符,其显示属性在BL中。显示后,光标位置不变
1——字符串中只含显示字符,其显示属性在BL中。显示后,光标位置改变
2——字符串中含显示字符和显示属性。显示后,光标位置不变
3——字符串中含显示字符和显示属性。显示后,光标位置改变
BH=页数(Page number)
BL=颜色属性(Attribute if string contains only characters)
CX=字数(Number of characters in string)
DH,DL=起始位置(Row,Column at which to start writing)
ES:BP=字串地址(String to Write)
al的输出模式我们先不去理会2,3两种值的情况.
由这个"函数原型"我们可以理解,int 10h的13号功能是将ES:BP处的CX个字符从BH页第DH行第DL页以属性BL显示出来,显示后光标位置变不变是由AL控制的,并且此过程没有返回值(前面说它是函数还抬举它了 :))
这里我们用到了ES,这也是为什么我们前面将其赋值的原因.
再看一下程序代码:
mov ax,bootmessage
mov bp,ax这两句的作用是将要显示的内容的地址传给BP.
mov cx,16是我们要显示的字符串的字数.你可以将bootmessage的内容改一下,再将此处的16改为对应的值试一下.
mov ax,01301h是我们要用13号功能,并且输出后光标后移.
mov bx,000ch,是定义页和属性
mov dl,0是定义起始位置
最后正式调用int 10h,调用后返回.去执行那个死循环.
下面一句是定义要输出的内容.
最后第二句是一个填充内容输出,只是为了凑足510个字节,最后加入必需的标志"55AA"
masm boot.asm -o boot.bin之后就可以用十六制进编译软件直接将其复制到虚拟硬盘或软盘的最前面512个字节了.
你还可以在代码中去掉
times 510-($-$$) db 0
dw 0xaa55这两句,而在十六进制编辑软件中在适当的位置填上"55AA"就可以了.
运行一下就可以看到效果了.红色的十六个字显示出来了.
下面来反汇编一下:
NDISASM -o 07c00 boot.bin >>disboot.asm 打开看一下内容如下:
00007C00 8CC8 mov ax,cs
00007C02 8ED8 mov ds,ax
00007C04 8EC0 mov es,ax
00007C06 E80200 call 0x7c0b
00007C09 EBFE jmp short 0x7c09
00007C0B B81E7C mov ax,0x7c1e
00007C0E 89C5 mov bp,ax
00007C10 B91000 mov cx,0x10
00007C13 B80113 mov ax,0x1301
00007C16 BB0C00 mov bx,0xc
00007C19 B200 mov dl,0x0
00007C1B CD10 int 0x10
00007C1D C3 ret
...
...
第五句的jmp short 0x7c09.这就是原来的jmp $.看一下,它就是不停的跳到自己这个位置上.
再看mov ax, 0x7c1e,这就是字符串的地址了,我们在十六位编辑器下找到这个地址,也就是第二行,最后第二个字开始的.下面我们将它改为别的字如"tresss studio",字符多少无所谓,反正字串后面都是00,我们不会破坏其它数据,保存后得新运行系统.字符串变了吧.
再看mov cx,0x10,这里的10是十六进制的,也就是十进制的16,在十六进制的011h处找到了它"10 00"我们改为"20 00"再向原来的字串后面多写几个字,重新运行虚拟机,呵呵,可以显示32个字符了.
还有mob bx,0xc,这是显示属性,将它改一下再运行就会发现字符的颜色变了.bl的低四位表示字体颜色,高四位表示背景颜色
看来写一个系统麻烦,但改一个系统还是挺快的.
您需要登录后才可以回帖 登录 | 论坛注册

本版积分规则

QQ|Archiver|手机版|小黑屋|sitemap|鸿鹄论坛 ( 京ICP备14027439号 )  

GMT+8, 2025-2-2 20:57 , Processed in 0.060723 second(s), 13 queries , Redis On.  

  Powered by Discuz!

  © 2001-2025 HH010.COM

快速回复 返回顶部 返回列表