《30天自制操作系统》笔记(11)——高分辨率

《30天自制操作系统》笔记(11)——高分辨率

进度回顾

上一篇介绍了定时器的初始化和使用方法。接下来就该实现多任务了。不过原作者在这之前写了关于提高分辨率的章节,本篇也总结一下设置显示器高分辨率的方法好了。本篇内容过于简单,算是小小的休息一下。

启用高分辨率的思路:检测显卡是否支持某种分辨率;如果支持,则通过INT 0x10指令启用之;否则使用任意显卡都支持的低分辨率。

VBE

历史上秦始皇扫平中原一统六国,其历史功绩之一便是在这之后统一了度量衡,从此全国人民在计算度量买卖的时候都有统一的标准了。秦始皇能够强制废除六国的货币、度量标准,但是显卡公司里没有一个能够成为秦始皇,也就造成了设置显示器分辨率的各种麻烦。

然而天下大势分久必合,显卡公司虽然无法合并为一,但市场不接受各自为政的混乱标准,因此多家显卡公司协商成立了VBE(Video Electronics Standards Association)即视频电子标准协会。VBE制作了专用的BIOS,基本上可以兼容所有的显卡分辨率设置。这个BIOS就称为"VESA BIOS extension"(VBE)。可以说VBE就是显卡公司之间统一的度量衡。

设置低分辨率

设置320*200这样的低分辨率时,使用"AH=0; AL=画面模式号码;INT 0x10;"就行了。

设置高分辨率

设置640*480等高分辨率时,要使用"AX=0x4f02;BX=画面模式号码;INT 0x10;"。

VBE的画面模式号如下。

  • 0x101……640*480*8bit彩色
  • 0x103……800*600*8bit彩色
  • 0x105……1024*768*8bit彩色
  • 0x107……1280*1024*8bit彩色

还有一些其它的模式,原作者省略了,我也就懒得知道了。

另外,QEMU中不能使用0x107。原因不明。

实际使用的时候,要把画面模式号加上0x4000,再赋值到BX中。

首先要判断计算机使用的是什么显卡。如果不能使用VBE,就只能用低分辨率了。

1     MOV        AX, 0x9000
2     MOV        ES, AX
3     MOV        DI, 0
4     MOV        AX, 0x4f00
5     INT        0x10
6     CMP        AX, 0x004f
7     JNE        scrn320

在这里,我们给ES赋值为0x9000,DI赋值为0,AX赋值为0x4f00,再执行INT 0x10。如果VBE存在,AX就会变成0x004f,否则就只能使用320*200的分辨率了。

显卡能利用的VBE信息,会写入内存中ES:DI指定的地址开始的512字节,所以这样要设置ES和DI。

然后要判断VBE版本。原作者的OS只支持VBE2.0以上的显卡。

1     MOV        AX, [ES:DI + 4]
2     CMP        AX, 0x0200
3     JB        scrn320            ; if (AX < 0x0200) goto scrn320

即使VBE版本是2.0以上,也不能保证所有的画面模式都能用。现在我们要通过VBE来查看一下画面模式0x105能不能用。

 
1     MOV        CX, VBEMODE        ; VBEMODE EQU 0x105
2     MOV        AX, 0x4f01
3     INT        0x10
4     CMP        AX, 0x004f
5     JNE        scrn320

如果AX是0x004f以外的值,那么所指定的画面模式就不能用。

此次取得的画面模式信息也被写入DS:DI开始的512字节处(即覆盖了之前检查VBE是否存在的结果)。

画面模式信息中重要的有如下几个。

  • WORD        [ES:DI + 0x00] ; 模式属性……bit7不是1就不好办
  • WORD        [ES:DI + 0x12] ; X的分辨率
  • WORD        [ES:DI + 0x14] ; Y的分辨率
  • WORD        [ES:DI + 0x19] ; 颜色数……必须为8
  • WORD        [ES:DI + 0x1b] ; 颜色的指定方法……必须为4(即调色板模式)
  • WORD        [ES:DI + 0x28] ; VRAM的地址

我们来确认如下三项内容:

  • 颜色数是否为8
  • 是否为调色板模式
  • 画面模式号码可否加上0x4000再进行指定
 1     CMP        BYTE [ES:DI + 0x19], 8
 2 
 3     JNE        scrn320
 4 
 5     CMP        BYTE [ES:DI + 0x1b], 4
 6 
 7     JNE        scrn320
 8 
 9     MOV        AX, [ES:DI + 0x00]
10 
11     AND        AX, 0x0080
12 
13     JZ        scrn320    ; 模式属性的bit7是0,所以放弃

如果上述步骤中没有跳入scrn320,那么就可以使用高分辨率。

 1     MOV        BX, VBEMODE+0x4000
 2     MOV        AX, 0x4f02
 3     INT        0x10
 4     MOV        BYTE [VMODE], 8 ; 记下画面模式(参考C语言)
 5     MOV        AX, [ES:DI + 0x12]
 6     MOV        [SCRNX], AX
 7     MOV        AX, [ES:DI + 0x14]
 8     MOV        [SCRNY], AX
 9     MOV        EAX, [ES:DI + 0x28]
10     JMP        keystatus

最后的JMP指令,用来让程序跳过后面的scrn320,直接进入在BIOS中查询键盘状态的地方。

下面就剩下scrn320这一小段了。

1 scrn320:
2     MOV        AL, 0x13 ; VGA图,320*200*8bit彩色
3     MOV        AH, 0x00
4     INT        0x10
5     MOV        BYTE [VMODE], 8 ; 记下画面模式(参考C语言)
6     MOV        WORD [SCRNX], 320
7     MOV        WORD [SCRNY], 200
8     MOV        DWORD [VRAM], 0x000a0000

我用VMware分别试验了640*480*8bit彩色、800*600*8bit彩色、1024*768*8bit彩色、1280*1024*8bit彩色这几种情况,发现均可以支持。另外,如原作者所说,QEMU不支持1280*1024*8bit彩色。这也是VMware比QEMU更强一些的一个证据。

截图如下。

下面是600*400分辨率的。

下面是1024*768分辨率的。

下面是1280*1024分辨率的。我的显示器不够显示这么大,所以截了2个图。

 

总结

启用高分辨率的思路:检测显卡是否支持某种分辨率;如果支持,则通过INT 0x10指令启用之;否则使用任意显卡都支持的低分辨率。

本篇算是个美化工作,下一篇就是期待已久的"多任务"了。

 

请查看下一篇《《30天自制操作系统》笔记(12)——多任务入门》

posted @ 2014-06-14 14:41  BIT祝威  阅读(6224)  评论(7编辑  收藏  举报