30天自制操作系统学习笔记----day_five

、实验主要内容

1.接受启动信息:

关键代码:

    

重点内容:

(1)通过指针来获得显示画面模式,这样可以避免当画面模式改变时系统无法正常运行的问题。

2.试用结构体:

关键代码:

重点内容:

  1. 如何理解结构体:struct后面是结构体的名字同时也是这个结构体的首地址,结构体可以理解为一个文件柜,各个变量可以看做接口,需要使用的时候接上这个接口即可,通过结构体对象.xxxx来访问。
  2. 试用箭头记号:

关键代码:

重点内容:

(1)这也是对指针访问的一种形式,这样子更形象一些,但使用这种方法访问程序会有危险。

4.显示字符:

关键代码:

重点内容:

  1. 如何理解这8个if呢?首先d做&运算的目的是检查不为1的位置,该位置就是它在VRAM中x的偏移量,也就是说在x的什么位置写入一个1,虽然有16个十六进制数,但8个if会将它们的每一个位置都检查一遍,符合条件则执行,执行完毕后就会看到下图的效果:

  1. 改进版,写入到数组去显示,代码如下:

那么又如何理解这个方法呢?很简单,只需要把p[0]-p[7]看做上图中的每一列就好,在绘图的时候就会遍历每一列,为1的点则画一个像素,这样的做法效率高而且简单。

运行截图:

5.增加字体:

关键代码:

重点内容:

  1. 制作显示的字体:作者已经提供好字体库,重点是理解它如何显示到屏幕上。首先通过makefont编译器生成二进制文件,也就是我们看到的那种01矩阵序列,然后二进制文件经过bin2obj程序的处理与ojb文件进行连接,最后变成汇编程序,经过一系列步骤后生成可执行文件,运行后即可看到欲显示的字符了。
  2. 外部程序使用字体库:通过extern关键字导入,务必保持c文件与字体库文件在同一个目录,否则会报错。Extern关键字的作用是声明该数据是外部导入数据,默认是根目录地址。
  3. 如何理解关键代码的putfont8()函数最后一个参数的表达式:如hankaku+’1’*16,这是一种寻址方式,首地址+要显示的目标字符的地址,16是偏移量。为什么是16呢?一共需要16行8位二进制才能显示一个字符呗。
  4. 运行截图:

6.显示字符串:

关键代码:

重点内容:

(1)如何理解这段代码呢:首先呢我们要明确字符串都是以0x00(对应的ASCII是’\0’)表示结尾,因此可以用于判断是否读取完整个字符串。再者字符串的首地址都是以字符串的首个字母开始,因为用*s可以表示首地址。这个代码其实就是将要画的字符存起来了,再调用putfont8()去画。本质还是画一个字符。X+=8是两个字符之间间隔几个像素。

(2)运行截图:

7.显示变量值:

关键代码:

重点内容:

  1. 如何将变量输出在屏幕上:按照之前的套路,肯定是先将要显示的东西写入VRAM才可以,那么如何将变量快速的写入到指定的内存中去呢?利用sprintf()即可,操作简单,只需要三个参数,显示的字符串数组(数组名就是它的首地址),输出格式、写入的值。binfo->scrnx起到导航作用,把当前变量值存储到%d里面,然后再将这个字符串写入s中。最后再将整个字符串s画出来。
  2. 由于是c语言函数,务必导入头文件:<stdio.h>
  3. 格式化输出说明:

(4)运行截图:

  

  1. 显示指针鼠标:

关键代码:

重点内容:

  1. 从本质来说,鼠标其实就是绘制一个箭头的图像。通过遍历鼠标数据(类似于txt文档那种图案),通过检测特定位置的标记绘制特定的像素(这个时候已经在内存的地址写好要显示的内容了),比较难的点就是如何拿到当前位置的背景颜色,作者也没有说明,只是将背景颜色当作一个参数传进来了。然后将鼠标的数据拷贝一份到VRAM里面去,再通过绘制函数画出来即可。总的来说就是根据图像数据得到在内存中的数据,最后存入VRAM即可显示出来。
  2. 代码如下:

Vram和vxsize是关于VRAM的信息,也就是vram第一个像素的地址以及这个画面的最大x分辨率。Pxsize和pysize是显示图像的长宽,px0和py0指定图像在界面上显示的位置,buf和bxsize分别表示存放图像的地址和每一行包含的像素数。

  1. 运行截图:

9.GDT与IDT初始化:

重点内容:

  1. 分段:通俗地讲,按照一定的方式将内存分割成许多不同的段,防止内存地址在使用的时候出现重叠。
  2. 表示一个分段需要的信息:段的大小、段的起始地址、段的管理属性(禁止写入、禁止执行、系统专用等等)。通过段寄存器来实现管理,只需要把对应设置设为1或者0即可。
  3. 不同的寄存器位数不一样,这个时候需要对寄存器不同的为进行编号,号码称之为段号,与内存上的段对应,不同的段有着不同的段号,管理的段的时候先找到段号即可。
  4. 如何设定段号呢?段号由一个表来维护,也就是GDT(全局段记录表),这个表在内存的某个地方,然后将内存的起始地址(或者某个段的起始地址)与有效设定个数放在cpu内被称作GDTR的特殊寄存器中就完成了设定。
  5. 顾名思义IDT就是中断记录表了,记录了0-255号中断号码与调用函数的对应关系,因此当鼠标中断时,调用函数里面的内容应该包括:获取当前鼠标的位置、在当前位置绘制鼠标。由于中断的速度极快以及人眼的视觉暂留效果,我们会看到鼠标移动的效果。
  6. 关键代码:

 

SEGMENT_DESCRIPTOR中存放了GDT的8字节内容,同理GATE_DESCRIPTOR存放了IDT的8字节内容,两者都是以cpu资料为基础的。Gdt被赋值为0x00270000,意思就是将内存地址0x270000~0x27ffff设为GDT(就是用该地址范围记录全局段记录表),同理IDT。

  1. 如何理解下图代码:

首先gdt的起始地址是0x270000,i每次迭代1,但gdt在地址却是前进了8个位置,原因就是gdt指针指向的结构体是8字节大小的。

、遇到的问题及解决方法

、程序设计创新点

(1)尝试着让界面显示中文字体:

关键代码:

重新对字体数据库进行编码即可。

运行截图:

猜你喜欢

转载自blog.csdn.net/weixin_42294984/article/details/83589542