让cinix工作在高分辨率模式

来源:互联网 发布:懒人眼镜 淘宝 编辑:程序博客网 时间:2024/06/05 09:15

以前的cinix一直工作在命令行模式(一行一行的黑底白字)下,说实话这个模式非常不美观,今天我们来让cinix运行在高分辨率模式,也就是给他赋予一层美丽的外衣--GUI图形界面,哈哈,开始做吧!!

首先要切换显示模式

操作系统启动的时候默认进入的是80X25文本模式(25行80列),该种模式下,占用的显存范围是0xb8000~0xbffff,每两个字节代表屏幕上显示的一个字符,低字节设置显示字符的ASKII码,高字节设置显示属性,具体可参考这篇文章点击打开链接。我们要做出一个漂亮的图形界面出来,显然不能让cinix工作在这种模式,所以首要任务是切换显示模式。那么问题来了,到底有哪些显示模式呢?怎么切换呢?

先解决第一个问题,有哪些显示模式。

(表1 VESA标准定义的显示模式(部份))

模式号

分辨率

色彩

0x100

640*400

256

0x101

640*480

256

0x102

800*600

16

0x103

800*600

256

0x104

1024*768

16

0x105

1024*768

256

0x106

1280*1024

16

0x107

1280*1024

256

0x10D

300*200

1:5:5:5

0x10E

320*200

5:6:5

0x10F

320*200

8:8:8

0x110

640*480

1:5:5:5

0x111

640*480

5:6:5

0x112

640*480

8:8:8

0x113

800*600

1:5:5:5

0x114

800*600

5:6:5

0x115

800*600

8:8:8

0x116

1024*768

1:5:5:5

0x117

1024*768

5:6:5

0x118

1024*768

8:8:8

0x119

1280*1024

1:5:5:5

0x11A

1280*1024

5:6:5

0x11B

1280*1024

8:8:8


  1. 上表列出了一些VESA标准的一些显示模式,先看色彩那一列,有两种形式,第一种是存数字,如16、256,第二种是带’:‘的,如“5:6:5”,“8:8:8”等,那么这两种形式各代表什么意思呢?首先来看第一种存数字的,表示屏幕上的一个像素点最多可以表示多少种颜色,比如说16表示的一个像素点最多可以表示16种颜色,此时需要先设置调色板,本篇文章不多介绍该模式,因为该模式最多只能显示16种或256种颜色,颜色数太少,如果显示一副真彩色图片的话,会产生很大的失真,如果读者对该模式好奇的话,后续我会写篇文章专门介绍如何设置调色板。再来看第二种带’:‘的,表明一个像素颜色的三基色(R/G/B)分别占用的位数。如5:6:5,表示R占用了5位,G占用了6位,B占用了5位,一共16位(5+6+5),也就是两个字节,此时一个像素共可以显示2的16次方种颜色,远远大于第一种存数字(16种或256种)所能显示的颜色数。再比如8:8:8表示R/G/B各占用了8位,一共24位,也就是三个字节,此时一个像素共可以显示2的24次方种颜色.
  2. 再来看“分辨率”那一列,如640×480表示总共有640行,每行有480个像素点,也就是共有640×480个像素点。
我们切换到0x118显示模式,该模式下,分辨率是1024×768,色彩是“8:8:8”,用更通俗的话来讲就是,有1024行,每行有768个像素点,每个像素点占用24位,也就是3个字节,每个像素点共能显示2的24次方种颜色。好了,如何切换呢?
按照VBE的标准,在AX寄存器中传入0x4f02,BX寄存器中传入待设置的显示模式号(如0x118)+ 0x4000,然后调用BIOS的0x10号中断,就可将显示模式设置为bx寄存器中指定的值。如果设置成功的话,ah寄存器中会返回0.
<span style="white-space:pre"></span>mov bx,0x4118mov ax,0x4f02int 0x10cmp ah,0x00jnz shift_failed
在qemu中能够切换成功,在vmware中不能切换到该显示模式,不知道为什么。
切换成功后,我们要获取该显示模式下的一些详细信息,如该模式下屏幕对应的显存起始地址是多少。我们知道,在80×25文本模式下,屏幕对应的显存起始地址是0xb8000,要在屏幕上打印字符只需往0xb8000开始的一段内存里写入数据即可。但在0x118显示下,屏幕对应的显存起始地址就不是0xb8000了,此时要再往0xb8000开始的一段内存里写入数据的话就不会显示在屏幕上了,所以我们要获取该模式下屏幕对应的显存起始地址。按照VBE的标准,在AX寄存器中传入0x4f01,CX寄存器中传入模式号(如0x118),然后调用BIOS的0x10号中断,可获得该显示模式下的详细信息,其中就包括屏幕对应的显存起始地址,如果调用成功的话,ah寄存器中会返回0,同时显示模式信息会被存放到内存的es:di指定的地址去。
;将该模式信息存入到特定内存地址去,这里是0x20000mov ax,0x2000mov es,axmov di,0mov cx,0x118mov ax,0x4f01int 0x10cmp ah,0x00jnz getinfo_failed
获取该显示模式的详细信息后,我们就可以从0x20000处取出该信息了,那么这些信息是什么呢?
struct vbe_mode_info{short modeattributes;char winAattributes;char winBattributes;short wingranularity;short winsize;short winAsegment;short winBsegment;int winfuncptr;short bytesperscanline;short xresolution;short yresolution;char xcharsize;char ycharsize;char numberofplanes;char bitsperpixel;char numberofbanks;char memorymodel;char banksize;char numberofimagepages;char reserved1;char redmasksize;char redfieldposition;char greenmasksize;char greenfieldposition;char bluemasksize;char bluefieldposition;char rsvdmasksize;char rsvdfieldposition;char directcolormodeinfo;<span style="color:#ff0000;">int physbaseptr;</span>int offscreenmemoffset;short offscreenmemsize;char reserved2[206];};
我们只关注physbaseptr字段,该字段就表示0x118显示模式下屏幕对应的显存起始地址。
我们定义一个char *类型的指针指向该地址,代码如下:
struct vbe_mode_info *vbe_info;vbe_info = (struct vbe_mode_info *)0x20000;char *video = (char *)vbe_info->physbaseptr;

得到显存起始地址后,我们就可以在屏幕上显示任意一种颜色(2的24次方种颜色中的一种)了,显示某一颜色示例:
<span style="white-space:pre"></span>vbe_info = (struct vbe_mode_info *)0x20000;char *video = (char *)vbe_info->physbaseptr;char *end = (char *)vbe_info->physbaseptr + 1024 * 768;for (; video < end; video += <span style="color:#ff0000;"><strong>3</strong></span>){*(unsigned int *)video = RGB(0xff,0x00,0x00);}
这里要特别注意每次循环完之后,video加3,也就是向后移动三个字节。为什么是移动3个字节呢?因为该显示模式下,R/G/B各基色都是8位,合起来24位,也就是3个字节,因此屏幕上的一个像素点要用三个字节来表示。如果是“5:6:5”的话,就是向后移动2个字节。
RGB函数实现如下:
int RGB(int r, int g, int b){if (r > 255)r = 255;if (g > 255)g = 255;if (b > 255)b = 255;return r*65536 + g*256 + b;}

好了,代码讲解完了,我们可以做实验了。
比如说这里我想显示红色,如下图所示:


可以看到,它的R/G/B值分别是0xff,0x00,0x00,RGB(0xff,0x00,0x00)将其合成一个整型数字,然后写到对应的显存,所以上面的代码就是在屏幕上显示红色,我们来看在qemu中的效果,如下图所示:


从0编写操作系统内核视频教程见:http://www.duobei.com/course/1574348473


0 0