再说下,我们的需求就是写个支持多任务,分时调度的操作系统。
这一节,先写个单任务的系统,开机能能够加载并执行即可。
OK,先上代码: funnyos_onetask.7z,文件列表如下:
编译命令:
只需双击执行build.bat即可生成Test.exe及FunnyOS.img。 FunnyOS.img是由buildimg.exe生成的。
FunnyOS.img为1.44M的虚拟软盘,即系统是放在软盘里的,可以用VirtualBox,Bochs,JPC运行。
FunnyOS.img的大致结构如下,前面512字节为引导扇区,开机BIOS执行完毕后会读取软盘加载执行这512个字节的引导代码。
引导代码会读取然盘的FAT12文件系统找出KERNEL.SYS文件,KERNEL.SYS文件是由exeflat.com程序将TEST.EXE转成BIN格式而来。
可以看到FunnyOS.img运行结果和Test.exe一致,如下:
在windows下运行的截图:
在virtualbox上运行FunnyOS.img截图:
OK,下面就是代码分析 test.c代码如下,很简单,先清空屏幕,然后在第一行显示” Funny OS Demo “。
main函数调用了PC.C中的函数,PC.C来自UCOS系统,
基础知识:
段地址0xB800是字符模式下显存的基地址,支持25行,80列显示。往0xB8000地址里面写如0x41,就能显示字符'A', 具体显示部分请查看PC.C我这里主要说明如何将一个EXE文件变成一个操作系统的"内核":
EXE文件除了包含二进制代码,还包含其它信息,如文件头和可重定位信息,这些是方便Windows操作系统加载运行的, 对于自己写的操作系统,这些信息没有意义,只需要其中的二进制代码即可。 将EXE文件转换成二进制文件,即BIN文件,可以用exeflat.com,但是默认转后BIN文件的入口地址为0x0, 也就是说将这个文件放在内存开始部分才能正确运行。 但要知道,内存的前1024个字节(0-0x3FF)是存放中断向量的,这部分内存不能被占用。 不仅如此,地址(0x400-0x5FF)这部分空间还存放了BIOS的基本数据,如当前时间等。 所以只有从0x600开始的内存空间才允许放置程序,所以生成BIN文件的命令为: exeflat TEST.EXE TEST.SYS 0x60 如之前所述,引导代码将KERNEL从软盘中读取到内存0x600处,然后就跳到test.c的main()函数执行,那引导代码是如何知道main()函数地址的呢? 看下生成的TEST.MAP,其中DATA段的段地址为0x1160,main()函数地址为0x113D。 OK,要执行main()函数,须将CS:IP设置为0x60:0x113D,DS设置为0x116,手动修改跳转代码,简单粗暴的跳到了main函数,下面的运行和test.exe就一样了。