My Os - 界面
前面我们实现了引导区,下面我们继续完善磁盘磁道的读写。
Day02 - 读磁盘
我们先把上一篇文章的 helloos.nas
改写一下,让他更像汇编语言的编写方式,并重命名为 ipl.nas
。ipl = initial progrom loader
1 | ; hello-os |
这段代码没啥好多说了,结构都在上一篇文章里了,就是用0x10中断来显示字符罢了。
AL = 0x03 | 16色字符模式 | 80 * 25 |
---|---|---|
AL = 0x12 | VGA图形模式 | 640 480 4 |
AL = 0x13 | VGA图形模式 | 320 200 8 |
AL = 0x6a | 扩展VGA图形模式 | 800 600 4 |
读磁盘
然后我改写 entry
段,加入磁盘读写的部分。新 entry
段代码如下:
1 | entry: |
下图是磁盘的结构:
柱面(cylinder)就是上图中「深黑色」的一圈一圈圆环状的区域,从外向内分别为柱面0、柱面1……柱面79,一共80个柱面。
磁头是一种针状的磁性设备,它可以从正反两面接触磁盘。软盘磁盘正反两面都能记录数据,因此我们有正反两个磁头,分别是磁头0号和磁头1号。
扇区(sector)就是把一个圆环(柱面),均匀分成几等份,每一份称为一个扇区。一个圆环有18个扇区,分别称为扇区1、扇区2……扇区18。
所以一张磁盘的容量为:80×2×18×512 = 1 474 560B = 1440KB。
我们制作的IPL启动区位于C0-H0-S1(柱面0,磁头0,扇区1),上面的代码就是读取第二个扇区到内存0x0820处。
出错重试
为了提升我们的操作系统的稳定性,在读磁盘出问题的时候,我们要重新读取。
1 | entry: |
这里需要我们掌握的就是磁盘重置的代码(AH = 0x02
是读磁盘,AH = 0x00
是磁盘复位)
1 | MOV AH,0x00 |
加 大 力 度
读取错误机制我们加上了以后我们就可以加大读取的力度,保证后面系统的使用了
1 | entry: |
EQU指令:是”equal”的缩写,相当于C语言中的#define命令,用来声明常数。“CYLS EQU 10”意思是”CYLS = 10”。
现在我们程序已经可以把软盘最初的10×2×18×512=184320byte=180KB
内容装载到内存里了,即这个程序可以用从软盘读取的数据填满内存0x08200~0x34fff
的地方。
Day03 - 着手开发操作系统
前面两天的工作是完善启动引导程序,现在我们要开始做的就是通过这个引导程序让指令跳到我们的操作系统里。并且我们将使用Makefile来统一编译我们的程序。
完整的 ipl.nas
代码:
1 | ; haribote-ipl |
我们可以看到其中增加里一句 JMP 0xc200
这就是我们引导程序结束后跳转到操作系统的代码。
我们把这个文件命名为 asmhead.nas
,这个命名的原因是核心代码打算用C语言写,但是前面图形界面的启动还是得靠汇编。
1 | ; haribote-os |
为了编译这个还特地写了 Makefile
文件
1 | TOOLPATH = ../z_tools/ |
文件架构如下:
1 | | |
这边程序运行起来就是一片黑,连 Hello World
都没有,所以就不上运行结果了。
Day04 - 导入用C编写的后半部分
为了调用c语言程序,作者在 asmhead.nas
里面添加了100行左右的代码,这个代码暂时不要求理解。
最新的 asmhead.nas
代码如下(请忽略注释的乱码):
1 | ; haribote-os boot asm |
下面就是我们的C语言部分:bootpack.c
1 | void io_hlt(void); |
这个就实现了一个简单的HLT功能,其中HLT我们以后还会多次用到,所以把他从C语言中剥离出来单独写成 naskfunc.nas
1 | ; naskfunc |
改写 Makefile
1 | TOOLPATH = ../z_tools/ |
好了,到这部分开始我们的操作系统就进入C语言时代了。
Day05 - 界面
在这个部分我们要完成界面的基础绘制。
想要在画面上画东西,只要往VRAM里写点东西就可以了。VRAM指的是显卡内存(video RAM),就是可以用来显示画面的内存。这一块内存可以像内存一样存储数据,它的各个地址都对应着画面上的像素。我们可以利用这个机制在画面上绘制各种各样的图案。
VRAM分布在内存分布图好几个不同的地方,不同画面模式的像素不一样,切换不同的画面模式,会使用不同VRAM,即不同画面模式可以使用的内存也不一样,我们预先把要使用的VRAM地址保存在BOOT_INFO里(VRAM EQU 0x0ff8
)。
首先我们要在 naskfunc.nas
中添加函数 _write_mem8
(在全局变量那里不要忘记声明,不然是无法调用的)
1 | _write_mem8: |
这个函数可以实现界面的绘制
故我们修改一下 bootpack.c
1 | void io_hlt(void); |
整个程序结构如下:
在命令行里输入
1 | .\make |
我们就可以在虚拟机中得到以下结果
好诶!不再是一团黑了。
如果我们把绘制部分改成:
1 | write_mem8(i, i & 0x0f); |
我们就可以在每一列上得到不同颜色的条纹了
最后我们搞点大动作,这里代码全是C语言就不过多解释了。
附上最后的 bootpack.c
1 | void io_hlt(void); |
效果如下