最近整理电脑,找到自己2年以前写的一个操作系统,放到网上共享一下。当时的代码有的地方看起来还比较幼稚。
系统开始时的bootloader部分是参考《自己动手写操作系统》做的,那本书里面如何搭建环境写得很详细,另外还有一些PC的基本概念写的也不错,推荐大家看一下;从分段分页开始我参考了Linux2.4的风格,没有按照那本书上的走。调试环境是Virtual PC和Bochs。
以下为当时写的总结:
2006-1-26 20:40 ReadMe.txt
实现了一个简易的操作系统,功能包括:
分段、分页的保护模式;
fat2文件系统下的二级引导过程;
elf格式内核的解析和加载过程;
保护模式下的时钟中断和键盘中断;
printf的实现,其中包括了系统调用;
屏幕的显示,包括部分的滚屏功能;
两个进程,每秒中进行一次时钟中断。
内存规划:
0000:0000--0000:03ff 实模式栈,总长1k
0000:0400--0000:04ff ROM BIOS 参数区(保留段)
0000:0500--0000:0fff free
0000:1000--8000:efff kernel.bin
8000:f000--8000:ffff 硬件检测参数
9000:0000--9000:01ff boot代码,总长512
9000:0200--9000:13ff fat内容,总长1200h
9000:1400--9000:2fff 根目录内容,总长1c00h
9000:3000--9000:fbff loader.com
9000:fc00--9000:ffff extended BIOS data area(保留)
a000:0000--b000:ffff Display adapter reserved(保留)
c000:0000--d000:ffff Reserved for rom expansion(保留)
e000:0000--e000:ffff Expansion of system ROM(保留)
f000:0000--f000:ffff System ROM(保留)
0x100000-- 搬移后的kernel.bin
0x101000--0x102000 页目录表
0x102000--0x104000 两个页表,寻址8M
0x104000--0x105000 零页
其中的硬件检测参数区8000:f000开始:
偏移0x1e8处开始的4字节为E820的数目。
偏移0x2d0--0x550的0x280字节为内存检测结果。
内核启动后会将这些信息拷到0页。
boot.bin:
当使用mov ax, [si+...]时,是把该地址处字节读入ah,+1处字节才读入al。原先没有考虑到这种情况,这在写loader.com的时候已经改正。
实模式下中断发生时,中断向量表放在0-1k的内存区间中,每个中断向量4个字节,总共256个。
loader.com:
自检内存大小。
将kernel.bin读到内存中。
进入保护模式。
在保护模式下将kernel.bin搬移到100000h处并跳转。(注意这里有一个elf的解析过程)
其它功能待定。
kernel.bin:
从此处开始使用C语言。
以后将会有很多东西参考Linux内核。
2005/12/19,周一,文件夹1-1
实现了一个简单的函数调用。
2005/12/20,周二,文件夹1-2
实现了代码的自举。
2005/12/21,周三,文件夹1-3
了解了fat12的结构,实现了软盘的读取,将fat12和根目录都拷贝到了内存中。
2005/12/22,周四,文件夹1-4
将部分函数调用改成了宏定义,成功压缩了编码。
2005/12/23,周五,文件夹1-5
实现了指定文件的查找,并增加了返回到dos的代码。
2005/12/24,周六,文件夹1-6
将制定文件拷贝到制定内存区域,并实现了跳转。改正了读取软盘的一个bug(第一次读的时候会出错)。最终还剩下60字节的空余。
2005/12/28,周三,文件夹2-1
实现了内存检测。
2005/12/29,周四,文件夹2-2
实现了kernel.bin的拷贝,并写了一个示例的kernel.bin。能够成功运行。
2005/01/03,文件夹2-3
现在能够成功跳入保护模式。
2006-1-4,文件夹2-4
实现了elf文件的解析。
2006-1-5 19:56 2-5
将源代码重新组织了一下,重写了makefile
2006-1-5 20:35 2-6
重新调换了保护模式中的gdtr
(后来证明这里是错的,gdtr中应该是线性地址,而不是这里的屋里地址)
2006-1-6 15:58 2-7
将内核的虚拟地址改成了0xC0100000
对前8M空间进行了分页操作。
2006-1-9 14:44 2-8
实现了软中断的调用。
gdt和idt中的内容都应该是经过页式映射的线性地址。
2006-1-9 23:43 3-1
实现了和C函数的整合。
2006-1-12 23:47 3-2
将光标的行列值改成了全局变量。
2006-1-14 03:19 3-3
实现了中断函数的初始化。
2006-1-14 23:28 3-4
实现了部分printf的功能,能够分辨%d和%x。
还没有在其中实现系统调用、/n/t、光标跟随移动等。
实现了一些字符串函数。
2006-1-15 23:01 3-5
完善了printf,当前拥有的功能包括
/t /n %x %d
已经能获取内存信息,目前暂不添加内存映射。
2006-1-16 22:03 3-6
完善了中断函数。
general_intr.c中的宏定义和中断的实现是值得好好研究的。
2006-1-17 20:38 3-7
操作了8259,实现了一个时钟中断。
2006-1-18 3:09 3-8
实现了光标的跟随移动。
2006-1-18 7:26 3-9
实现了滚屏操作,但目前只支持一个控制台。
2006-1-20(home) 18:01 3-10
实现了键盘的读取。
inb等函数也已实现。
2006-1-24 11:02 3-11
实现了不同权限之间的切换。
2006-1-24 22:22 3-12
实现了一个简单的陷阱门。
2006-1-25 17:32 3-13
添加系统调用实现了write_console,目前暂时还没有控制台的概念。
此系统调用还实现了返回值的功能,比较有趣的。
2006-1-26 20:04 3-14
实现了进程切换。