操作系统实验第四天:C语言与画面显示的练习

一、实验主要内容
内容1:用C语言实现内存写入
想要画东西,只需要往VRAM里写点什么就可以。但是在C中有没有直接写入指定内存地址的语句。所以创建一个有这种功能的函数。即书上的naskfunc.nas部分。这个函数类似于C语言中的write_mem8(0x1234,0x56)。此时参数指定的数字就存放在内存里,分别是:
第一个数字的存放地址 [ESP+4]
第二个数字的存放地址 [ESP+8]
第三个数字的存放地址 [ESP+12]
第四个数字的存放地址 [ESP+16]
我们想取得用参数指定的数字0x1234或0x56的内容,就用MOV指令读入寄存器。因为CPU已经是32位模式,所以我们积极使用32位寄存器。
除此以外,还需要给naskfunc.nas增加一行,也就是INSTRSET指令,其是告知nask“这个程序是给486使用的”,如果见到EAX,会解释成寄存器名。如果不指定的话,会将其解释成标签,因为在老的CPU中,会用EAX来做标签。
修改C语言,添加循环函数,使其填充0xa0000-0xaffff的内存。
在这里插入图片描述

运行结果如下(因为第15种颜色对应的颜色正好是纯白):
在这里插入图片描述

内容2:条纹图案
想要生成各种各样的条纹图案,只需要给内存地址合适的颜色安排即可。代码修改如下:
在这里插入图片描述

可以看到,就是对填充区域进行了一下修改,从一个常数15改成了i&0x0f。那么运行结果就变成了条纹状,如下:
在这里插入图片描述

因为颜色的安排是递进变化的,所以最后的图案也就有了规律的变化。
内容3:挑战指针
在这部分又对代码进行了一下修改,如下:
在这里插入图片描述

可以看到,这里不再调用那个函数,而是直接用指针的形式进行对VRAM各个地址的赋值。这里指针其实就充当了一个寄存器的作用,在这里也就是相当于一个BYTE型的地址。
但是这样写会有警告信息,因为赋值语句没有经过类型转换,由整数生成了指针。
所以应该按如下方式写:p=(char *) i ;
内容4:指针的应用(1)
在内容3的基础上,对代码进行了二次修改,即如下形式:
在这里插入图片描述

所做的事和之前是一样的 ,只是换了种表示方法。
内容5:指针的应用(2)
除了内容4中的修改方式,还可以进行如下修改:
在这里插入图片描述

最后的结果都是一样的,但是要注意这里的P[i]并不是数组的意思,仅仅是一种省略写法,与数组在本质上并没有关系。
内容6:色号设定
电脑颜色都是用#ffffff一类的数来进行表示,这就是RGB方式,用6位十六进制数来表示颜色。而现在使用的是320*200的八位颜色模式,色号使用8位(二进制)数,也就是只能使用0~255的数,比如说25号对应的就是#ffffff,26号对应的是#123456这样子。这种方式就叫做调色板。
作者使用了下面16种颜色:
在这里插入图片描述

并重新修改了bootpack.c函数,在里面对颜色编写进行初始。
在这里插入图片描述

在这里将六位十六进制表示颜色的方式切割成了三个两位十六进制,方便之后调色板的调用。
在这里插入图片描述

该函数就是由调色板访问步骤所产生的函数,其主要所做的事情是多次调用io_out8函数。那么io_out8函数是用来做什么的呢?其是向指定装置里传送数据的函数。
CPU不仅与内存相连,还与设备相连,那么就必须要有向这些设备发送电信号或者从这些设备中取得信息的指令。向设备发送电信号的是OUT指令,从设备取得电信号的是IN指令。
在这两个指令中,为了区别不同的设备,那么就需要使用设备号。当然,在C语言中能够没有与IN或者OUT指令相当的语句,因此只能通过汇编语言来实现。
关于调色板的访问步骤:
调色板的访问步骤。
首先在一连串的访问中屏蔽中断(比如CLI ).
将想要设定的调色板号码写人0x03c8,紧接着,按R,G,B的顺序写入Ox03c9。如果还想继续设定下一个调色板,则省略调色板号码,再按照RGB的顺序写入Ox03c9就行了。如果想要读出当前调色板的状态,首先要将调色板的号码写人0x03c7,再从Ox03c9读取3次。读出的顺序就是R,G,B。如果要继续读出下一个调色板,同样也是省略调色板号码的设定,按RGB的顺序读出。
如果最初执行了CLI,那么最后要执行STI。
什么是CLI和STI呢?
CLI是将中断标志置为0的指令,而STI是将这个中断标志置为1的指令,其与CPU的中断处理有关系。当CPU遇到中断请求时,是立即处理中断请求(中断标志为1),还是忽略中断请求(中断标志为0),就由中断标志位决定。
作者还介绍了EFALGS寄存器。它是由FLAGS的16位寄存器扩展而来的32位寄存器。FLAGS是存储进位标志和中断标志的寄存器。对于中断标志,没有类似的JI或者JNI指令,只能读入EFLAGS,再检查第9位是0还是1。进位标志是EFLAGS的第0位。
set_palette中想要做的事情是在设定调色板之前首先执行CLI,但处理结束以后以后一定要恢复中断标志。因此需要记住最开始的中断标志是什么。所以我们制作了一个函数io_load_eflags,读取最初的eflags值。
PUSHFD指令是将标志位的值按双字长压入栈,POPFD是按双字将标志位从栈弹出。即PUSHFD POP EAX 是指先将EAFLAGS压入栈,再将弹出的值代入EAX。另一方面,PUSH EAX POPFD正好相反。
运行:

在这里插入图片描述
可以看到和之前相比,图案没有变化,颜色变了。
内容7:绘制矩形
画面上有320*200个像素,那么像素坐标(x,y)对应的VRAM地址应该按照下面公式计算。 根据上式计算像素的地址,往该地址的内存里存放某种颜色的号码,那么画面上该像素的位置就出现相应的颜色。循环上述操作就能画一条长长的水平直线,再向下循环这条直线,就能画出很多直线,也就是矩形。
按作者的代码思路,运行结果如下:
在这里插入图片描述

最后作者还是按照相同的思路,设计了一个看上去像操作框的图案,如下:
在这里插入图片描述

本次内容大致就这些。
二、遇到的问题及解决方法
问题1:
在这里插入图片描述

在上图中,为什么要除以4?
答:
每一个颜色都是有0-255个色调,代表了颜色的明暗程度。那么在除以4之后,色调程度便随之下降,那么最后合成的颜色也可以变暗。尝试了不进行除以四的操作,可以看到颜色偏黑。作者应该只是在这样尝试之后对颜色进行明暗的调整。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值