30天自制操作系统day5
一、实验主要内容
1、 内容1:接收启动信息
由于我们之前的代码里面的值,例如xsize、ysize的值都是在中断号0x10下的模式,一旦我们切换了模式,代码就不能正常运行,所以现在通过指针来获得画面模式的信息,这样可以避免当画面模式改变时系统无法正常运行的问题。这里的0xff4等对应asmhead.nas中相应参数地址。画面模式的参数保存在那些地址中,画面模式的改变即那些参数的改变,所以我们这里借用指针可以避免这个问题。
2、 内容2:结构体
最开始的struct指令只是把变量声明集中起来,统一叫做“struct BOOTINFO”。有了这样的声明,以后“struct BOOTINFO”就可以作为一个新的变量类型。
为了让程序能一看就懂,要这样写结构体的内部变量:在结构体变量名的后面加一个点(.),然后在写内部变量名。
想要表示结构体中的scrnx,可以用如下表示
3、 内容3:试用箭头记号
可以连xsize都不用,直接用binfo->scrnx代替xsize
4、 内容4:显示字符
以前我们显示字符主要靠调用BIOS函数,但这次是32位模式,不能在依赖BIOS了。
显示字符:
字符可以用8*16的长方形像素点阵来表示。每行通过对应点的二进制数显示出来,在数据对应为1的地方打点。
怎么将这种字体数据写到程序里?
因为C语言无法用二进制数记录数据,只能写成十六进制或八进制。所以一种解决方法是将刚才的0/1排列重写成16进制。
从左到右是坐标到数值的转化;
遍历每一个排列,是1的话就将其着色;
整理一下程序,使得程序简短一点
运行一下,就能显示出字符“A”
5、 内容5:增加字体
因为上个程序只能显示“A”字符而不能显示其他的字符,所以我们需要显示其他更多的字符。
用一个文本文件来储存256个字符的显示方式
改写C语言代码:
像这种在源程序以外准备的数据,都需要加上extern属性。这样,C编译器就能够知道它是外部数据,并在编译时做出相应的调整。
我们的txt文件中有256个字符,每个字符的序号都和其ASCII码相同,而每个字符占16个字节,所以我们想得到某个字符的位置只需要计算hankaku+(其ASCII码)*16,ASCII码可以用‘字符’来代替。
根据代码,预计运行是会显示“ABC 123”
make run
6、 内容6:显示字符串
因为仅仅显示六个字符就要很多代码,所以制定一个函数,用来显示字符串
所谓字符串是指按顺序排列在内存里,末尾加上0x00而组成的字符编码。
所以s是指字符串前头的地址,而使用*s就可以读取字符编码。
make run
7、 内容7:显示变量值
因为Windows的调试器不能对我们的操作系统进行调试,所以我们要自己做一个调试器。
在做出调试器之前,只能通过显示变量值来查看确认问题的地方。
怎么显示变量的值?为什么不做个printf函数?
使用sprintf函数,因为sprintf不是指定格式输出,只是将输出内容作为字符串写在内存中。
不做printf函数的原因是各个操作系统输出字符串的方法都不一样,不管如何精心设计,都不可避免的要使用操作系统的功能。sprintf不同,它只对内存进行操作,所以可以应用于所有操作系统。
要在C语言中使用sprintf函数,就必须在原程序的开头写上#include<stdio.h>。
sprintf函数的使用方法是:sprintf(地址,格式,值,值,值……)。这里的地址指定所生成字符串的存放地址。
make run
8、 内容8:显示鼠标指针
首先将鼠标指针的大小定为1616,先准备1616=256字节的内存,然后往里面写入鼠标指针的数据,我们把这个程序写在init_mouse_cursor8里。
变量bc是指back-color,也就是背景色,要现实背景色,只需将buf中的数据复制到VRAM中去就可以了。
putblock8_8函数:通过将buf中的数组复制到vram中从而将背景色显示出来。
pxsize和pysize是要显示鼠标的大小,都为16。px0和py0制定鼠标在画面上显示的位置。buf和bxsize分别指定图形的存放地址和每一行含有的像素数。
make run
9、 内容9:GDT与IDT的初始化
GDT与IDT都是与CPU有关的设定,为了使操作系统能够使用32位模式,需要对CPU做各种设定。
分段:将合计4GB的内存分成很多块,每一块的起始地址都看作0来处理,有了这个功能,任何程序都可以写上一句ORG0。像这样分割出来的块,就成为段。
分页:分页的思想是有多少个任务就要分多少页,还要对内存进行排序。
GDT:表示全区段号记录表(用来管理分段中段的信息)。
IDT:表示中断记录表(用来管理中断号和处理函数的)。要使用鼠标,就要进行中断。
GDT和IDT都是与CPU有关的设定,对其进行特定的设置,才能使得鼠标动起来。
GDT和IDT的相关数据是存放在内存中,GDT中内存的起始地址和有效设定个数存放在GDTR的寄存器中,而IDT则放在IDTR这个寄存器中。
二、遇到的问题及解决方法
1、 描述问题1
解读一下P93面的代码
因为字符是用8*16长方形像素点阵表示,所以用for语句将8个像素的程序循环16遍就可以显示出一个字符了。
每次循环检测8个像素,从左到右;以第一个为例,0x80转化为二进制就是10000000,如果第一位中存在1,与运算之后为非零,就会对这个地方进行涂色,以此类推。
2、 描述问题2
怎么显示变量的值?为什么不做个printf函数?
使用sprintf函数,因为sprintf不是指定格式输出,只是将输出内容作为字符串写在内存中。
不做printf函数的原因是各个操作系统输出字符串的方法都不一样,不管如何精心设计,都不可避免的要使用操作系统的功能。sprintf不同,它只对内存进行操作,所以可以应用于所有操作系统。
3、 描述问题3
怎么实现将鼠标的位置写在屏幕的中间的?
通过mx,my来定位屏幕中心点
然后通过putblock8_8(即上图所示的函数),就能够将鼠标位置写到屏幕中
三、程序设计创新点
1、描述创新点1
对长方形点阵的数据进行更改,使其输出的字符为“X”
2、描述创新点2
对显示的字符串进行更改,是的输出的字符串为名字缩写以及号码
输出显示如下
3、 描述创新点3
通过改变显示字符串的编码,使得输出的字符串重叠增加以及间隔的改变
不错,很有艺术感,就是有点儿看不清楚
4、 创新描述4
将鼠标位置进行更改,使其位置出现在右上方
鼠标的位置可任意设置,根据自己的喜好即可。
30天自制操作系统1~15天日志:https://download.csdn.net/download/weixin_43979304/15320819?spm=1001.2014.3001.5503