30天自制操作系统第5天内容要点
回顾第四天的内容,在第4天,我们已经成功的绘制了操作系统的界面。下面我们来分析一下第四天程序目录下的几个源代码文件:
a.ipl10.nas:初始化程序加载;
b.bootpack.c:操作系统内容部分(C代码实现)
c.naskfunc.nas:操作系统内容部分(汇编代码实现)
d.asmhead.nas:加载显卡模式(部分代码用来支持C和汇编的混合编程)
1.接收启动信息
为什么不提倡在bootpack.c里面直接给vram,xsize,ysize这些变量赋值呢?
主要是考虑到我们之前在asmhead.nas里面我们调用显卡函数并选择模式,并在asmhead.nas中配置好了vram,xsize,ysize函数,如果我们想换其他显卡模式,那么所有这些值都要修改。鉴于此,我们在bootpack.c中之间引用asmhead.nas中的值。
而vram,xsize,ysize分别存在0x0ff8,0x0ff4,0x0ff6这些地址中。
所以,在第一小节我们声明了3个指针分别是binfo_scrnx,binfo_scrny,binfo,binfo_vram,分别存储0x0ff4,0x0ff6,0x0ff8这些变量值。
此外,第一小节把第四天画的矩形框的内容,用一个init_screen函数封装起来了。
2.试用结构体
将许多有意义且相关联的变量放在一个结构体里面。比如:scrnx,scrny,vram,cyls,leds,vmode。
结构体的声明:
1 struct BOOTINFO 2 { 3 char cyls,leds,vmode,reserve; 4 short scrnx,scrny; 5 char *vram; 6 };
结构体定义变量或指针变量
struct BOOTINFO *binfo;//(*binfo).cyls
struct BOOTINFO binfo;// binfo.cyls
3.试用箭头记号
struct BOOTINFO *binfo;
binfo->vram,binfo->scrnx,binfo->scrny;
这些都是简单的指针调用,学习C或C++之前应该都学过。
4.显示字符
字符可以用8*16的长方形像素点阵来表示,例如字符'A' 可以这样表示:
我们可以用一个静态的数组来保存。
接下来用for循环对画8个像素的程序循环16遍,就可以显示这个字符。显示一个字符的函数封装如下:
参数解释:vram,x,y用来确定第一个像素点的位置。c是需要显示的颜色,xsize是x方向的分辨率,font是字符数组的编码表示。
5.增加字符
hankaku.txt有要用到的字符的所有编码,是用.和*来表示的,需要将这个文件转化成目标文件;
首先使用makefont.exe工具编译成hankaku.bin文件,然后用bin2obj转换成目标文件。
(注意:如果C语言中要使用这种字体数据,需要在申明字符数组之前加extern 关键字)
6.显示字符串
制作一个输出字符串的函数如下:
因为字符串最后是以' '字符结束,所以最后的结束判断是*s!=0x00。
7.显示变量值
使用sprintf函数可以显示变量的值,它是printf的同类,我们不能随便使用printf函数,但是sprintf函数是可以的。因为sprintf函数不是按指定格式输出,只是将输出内容作为字符串写在内存中。
这个sprintf函数,是名为GO的C编译器附带的函数,它在制作者的精心设计下能够不适用操作系统的任何功能。
要在sprintf函数,需要添加C语言的头文件#include<stdio.h>
sprintf函数的使用方法:sprintf(地址,格式,值,值,值,,,....)这里的地址指的是所生成字符串的存放地址。
格式上基本上只是单纯的字符串,如果有%d这类记号,就替换成后面的内容。
8.显示鼠标指针
使用16*16的像素点阵,保存在mouse[]数组中
显示在屏幕上的px0,py0的位置
9、GDT与IDT的初始化
GDT:全局段号记录表
IDT:中断记录表
所谓分段:打个比方说,就是按照自己喜欢的方式,将合计4GB的内存分成很多块了,每一块的起始地址都看作0来处理。
为了表示一个段,需要有以下信息:
段的大小是多少;
段的起始地址是多少;
段的管理属性(禁止写入,禁止执行,系统专用)。
IDT记录了0~255的中断号码与调用函数的对应关系。
一般需要先进行GDT的设定,然后设定IDT。
gdtidt的初始化