3 提高分辨率(2)(harib11e)

只能在模拟器上运行的操作系统实在没什么意思,还是想在真机上运行。所以,我们来把前一节的程序改写一下,让它能在真机上运行。

我们不能断定真机上使用的是什么样的显卡。有的公司尚未与VESA进行合作。如果是这种公司的产品,由于不能使用VBE,所以大家只能忍耐一下,使用320×200的画面了。

本次的asmhead.nas节选

  1. ; 确认VBE是否存在
  2. MOV AX,0x9000
  3. MOV ES,AX
  4. MOV DI,0
  5. MOV AX,0x4f00
  6. INT 0x10
  7. CMP AX,0x004f
  8. JNE scrn320

在这里,我们给ES赋值为0x9000,给DI赋值为0,给AX赋值为0x4f00,再执行“INT 0x10”。如果有VBE的话,AX就会变为0x004f。要是AX没有变为这个值,很遗憾,就只能使用320×200的画面了。

至于为什么要对ES和DI进行赋值,是因为此显卡能利用的VBE信息要写入到内存中以ES:DI开始的512字节中,赋值是为了指定写入地址。

■■■■■

在“纸娃娃操作系统”中,如果VBE的版本不是2.0以上,就不能使用高分辨率。所以我们要先调查一下VBE的版本。

本次的asmhead.nas节选

  1. ; 检查VBE的版本
  2. MOV AX,[ES:DI+4]
  3. CMP AX,0x0200
  4. JB scrn320 ; if (AX < 0x0200) goto scrn320

程序进行到这里,下一步要通过VBE来查看一下画面模式0x105能不能使用。即使VBE 的版本是VBE 2.0,也不能保证所有的画面模式都可以使用。真是麻烦呢。因为如果局限于画面模式0x105,那些想使用其他画面模式的人就要抱怨了。为了调查这种模式能否使用,我们首先这样设定:

  1. VBEMODE EQU 0x105

本次的asmhead.nas节选

  1. ; 取得画面模式信息
  2. MOV CX,VBEMODE
  3. MOV AX,0x4f01
  4. INT 0x10
  5. CMP AX,0x004f
  6. JNE scrn320

在这里我们对AX的值也进行了确认。如果它是0x004f以外的值,就意味着所指定的画面模式不能使用。

此次取得的画面模式信息也被写入内存中从ES:DI开始的256字节中。因为ES和DI都保持刚才的值不变,所以画面模式信息会覆盖VBE版本信息从而导致其消失,但是只要版本能确认,后面就不需要这个信息了,所以大家不必在意。

■■■■■

在画面模式信息中,重要的信息有如下6个。

WORD   [ES : DI+0x00] : 模式属性……bit7不是1就不好办(能加上0x4000)

WORD   [ES : DI+0x12] : X的分辨率

WORD   [ES : DI+0x14] : Y的分辨率

BYTE   [ES : DI+0x19] : 颜色数……必须为8

BYTE   [ES : DI+0x1b] : 颜色的指定方法……必须为4 (4是调色板模式)

DWORD  [ES : DI+0x28] : VRAM的地址

在这6项信息当中,我们来确认如下3项:

  • 颜色数是否为8

  • 是否为调色板模式

  • 画面模式号码可否加上0x4000再进行指定

本次的asmhead.nas节选

  1. ; 画面模式信息的确认
  2. CMP BYTE [ES:DI+0x19],8
  3. JNE scrn320
  4. CMP BYTE [ES:DI+0x1b],4
  5. JNE scrn320
  6. MOV AX,[ES:DI+0x00]
  7. AND AX,0x0080
  8. JZ scrn320 ; 模式属性的bit70,所以放弃

如果这些确认都完成的话,就可以跟大家说了:“恭喜。可以使用所指定的VBE画面模式了。那就尽情享受大画面的乐趣吧!”所以我们决定进行画面模式的切换。而一旦我们完成了切换,就可以将分辨率及VRAM的地址等信息复制到BOOTINFO中了。

本次的asmhead.nas节选

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

最后的JMP指令,用来让程序跳过后面的scrn320,而让其跳转至在BIOS中查询键盘状态的地方。scrn320程序我们紧接着就要写。

■■■■■

那么当出现VBE不存在,版本不够,模式有问题的情况下,我们又该怎么办呢?没办法,我们只能使用迄今为止的320×200画面。

本次的asmhead.nas节选

  1. scrn320:
  2. MOV AL,0x13 ; VGA图、320x200x8bit彩色
  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

好,这样就大功告成了。首先要确认在模拟器上能否正常运行。运行“make run”。OK,运转正常。

下面确认在真机上能否正常运行。“make install”一下。完成以后,按下桌面上的开关。哦,顺利运行。

如果想试一试不能顺利运行是什么样,可以设定画面模式为0x107,再在模拟器上执行就可以了。画面还是320×200哦。

■■■■■

恭喜各位实现了高分辨率,不过在广大读者之中,可能有人还在使用不支持VBE 2.0的显卡,所以今后笔者还是要使用以前的320×200画面截图。而且这样的图片,文字和鼠标指针都显得比较大,容易看。

3 提高分辨率(2)(harib11e) - 图1

画面很宽

这次我们对于VBE的使用方法做了多方面的介绍,其中笔者参考了下面的网页。

http://community.osdev.info/?VESA

大家有兴趣的话也看一下吧。