babyos (四)—— SVGA、VBE基础与切换到髙分辨率模式

注:以下程序系原创,若有bug欢迎指正,若有问题欢迎交流,转载请注明出处。若能有益于一二访客,幸甚。


1.VGA

VGA(Video Graphics Array)即视频图形阵列,是IBM在1987年随PS/2机推出的。
VGA主要由七大块组成:图形控制器、显示存储器、定序器、CRT控制器、数据串行发生器、属性控制器和数模转换器DAC。

2.VBE

IBM的VGA标准是显示卡发展史上的一块丰碑。但后来无法满足人们的需要,于是市场上出现了TVGA、S3系列、Cirrus Logic、ET等为首的一批显示卡,提供了比VGA分辨率更高,颜色更丰富的显示模式,又兼容VGA显示卡,它们被统称为Super VGA(SVGA)。
各种不同的SVGA之间的显示控制各不相同,带来软件兼容性问题,为此视频电子学标准协会VESA(Video Electronics Standards Association)提出了一组附加的BIOS功能调用借口——VBE(VESA BIOS EXTENSION)标准,从而在软件接口层次上实现了各种SVGA显示卡之间的兼容性。时至今日,所有的显示卡OEM厂商都提供了符合VESA SUPER标准的扩展BIOS。通过一组INT 10H中断调用(AH=4FH),可以方便地使用VESA SVGA的扩展功能而不必了解各种显示卡的硬件细节。
Super VGA的扩充显示能力关键取决于对较大显示存储器的寻址能力。
各Super VGA 卡提供的分辨率远高于VGA,VESA VBE均赋予一个标准的16位模式号(实际上是9位,其他各位为标志位或留给以后扩充)。

3.VBE功能调用和返回值

VBE功能调用的共同点:
1)AH必须等于4FH,表明是VBE标准;
2)AL等于VBE功能号,0<= AL <= 0BH;
3)BL等于子功能号,也可以没有子功能;
4)调用INT 10H;
5)返回值

VBE返回值一般在AX中:
1)AL=4FH:支持该功能
2)AL!=4FH:不支持该功能;
3)AH=00H:调用成功;
4)AH=01H:调用失败;
5)AH=02H:当前硬件配置不支持该功能;
6)AH=03H:当前的显示模式不支持该功能;

4.VBE 功能

-----------------------------------------------------------
				功能0x00:返回VBE信息
------------------------------------------------------
入口:
	AX			0x4F00
	ES:DI		指向VBE信息块的指针
出口:
	AX			VBE返回值
------------------------------------------------------------

-----------------------------------------------------------
			功能0x01:返回VBE特定模式信息
------------------------------------------------------
入口:
	AX			0x4F01
	CX			模式号
	ES:DI		指向VBE特定模式信息块的指针
出口:
	AX			VBE返回值
------------------------------------------------------------

-----------------------------------------------------------
			功能0x02:设置VESA VBE 模式
------------------------------------------------------
入口:
	AX			0x4F02
	BX			模式号
出口:
	AX			VBE返回值
------------------------------------------------------------
当设置模式失败时,返回错误代码,一般返回AH=01H

VESA 2.0以上增加了BX中D14,D15的位定义,完整定义如下:
BX = 模式号
	D0~D8:9位模式号
	D9~D13:保留,必须为0
	D14 = 0:使用普通的窗口页面缓存模式,用VBE功能05H切换显示页面
		= 1:使用大的线性缓存区,其地址可从VBE功能01H的返回信息ModeInfo获得
	D15 = 0:清除显示内存
		= 1:不清除显示内存
------------------------------------------------------------

5.示例

检查VBE可否使用、版本、模式0x103,并切换到模式0x103(800*600, 256色):

# 本程序测试VBE(VESA BIOS EXTENSION)显示模式,然后切换到1024*768 256色模式,
# 并通过软盘读取Baby OS 的简单LOGO,显示在屏幕上
# 2012-12-28 21:03
# guzhoudiaoke@126.com

.section .text
.global _start
.code16

_start:
	jmp		main

#--------------------------------------------------------------
# 清屏函数:
#	设置屏幕背景色,调色板的索引0指代的颜色为背景色
clear_screen:				# 清屏函数
	movb	$0x06,	%ah		# 功能号0x06
	movb	$0,		%al		# 上卷全部行,即清屏
	movb	$0,		%ch		# 左上角行
	movb	$0,		%ch		# 左上角列	
	movb	$24,	%dh		# 右下角行
	movb	$79,	%dl		# 右下角列
	movb	$0x07,	%bh		# 空白区域属性
	int		$0x10
	ret

#----------------------------------------------------------------
# 设置VGA 0x13显示模式函数
set_video_mode_0x13:
	movb	$0,			%ah			# 功能号0x0
	movb	$MODE_0x13,	%al			# 显示模式
	int		$0x10

	movw	$0x13,		video_mode
	movw	$320,		screen_x
	movw	$200,		screen_y
	movl	$0xb8000,	video_ram
	
	ret

#----------------------------------------------------------------
# 设置VBE 0x103显示模式
#	因第一次写此类程序,只考虑了可读性,未考虑效率,比如al、ah分开赋值等
set_video_mode_vbe_0x103:
	# 确认VBE是否存在
	movw	$BUFFER_SEG,		%ax
	movw	%ax,				%es
	movw	%ax,				%ds
	xorw	%di,				%di
	
	# 下面检查是否支持VBE及VBE版本
	movb	$0x4f,				%ah			# VBE标准
	movb	$0x00,				%al			# 功能号
	int		$0x10

	cmp		$0x004f,			%ax			# 若有VBE,AX应该为0x004f
	jne		1f
	movw	0x04(%di),			%ax
	cmp		$0x0200,			%ax			# 若VBE版本不是2.0以上,不能使用髙分辨率
	jb		1f

	# 下面检查MODE_VBE_0x13的参数
	movw	$MODE_VBE_0x103,	%cx
	movb	$0x4f,				%ah			# 表明VBE标准
	movb	$0x01,				%al			# 子功能号
	int		$0x10

	cmpb	$0x00,				%ah			# 是否调用成功
	jne		1f
	cmpb	$0x4f,				%al			# 是否支持该模式
	jne		1f
	cmpb	$8,					0x19(%di)	# 颜色是否占8bit
	jne		1f
	cmpb	$4,					0x1b(%si)	# 颜色的指定方法是否为4,即调色板方式
	jne		1f
	movw	(%di),				%ax
	andw	$0x0080,			%ax
	jz		1f								# AX第7个比特是否为1,该位表示线性帧缓存是否有效

	# 下面设置模式
	movw	$MODE_VBE_0x103,	%bx
	addw	$0x4000,			%bx			# BX第14个比特表示是否使用大的线性缓存区,故置位
	movb	$0x4f,				%ah			# 表示使用VBE标准
	movb	$0x02,				%al			# 功能号,表示设置模式
	int		$0x10

	# 下面记录切换到的模式的一些参数信息
	movw	$MODE_VBE_0x103,	video_mode
	movw	0x12(%di),			%ax
	movw	%ax,				screen_x
	movw	0x02(%di),			%ax
	movw	%ax,				screen_y
	movl	0x28(%di),			%eax
	movl	%eax,				video_ram
	movw	$1,					%ax
	ret
1:
	movw	$0,					%ax
	ret

	
#----------------------------------------------------------------
# 设置背景颜色为深蓝色
set_screen_bk_color:
	movw	$VIDEO_PALLETE_PORT,	%dx
	movb	$PA_INDEX_BACKGROUND,	%al
	outb	%al,					%dx

	movw	$COLOR_SELECTION_PORT,	%dx
	movb	$0,						%al		# 红
	outb	%al,					%dx
	movb	$0,						%al		# 绿
	outb	%al,					%dx
	movb	$18,					%al		# 蓝(亮度18/63)
	outb	%al,					%dx
	ret

#----------------------------------------------------------------
# 通过写显存绘制一些像素点:
#	首先设置调色板索引1处的颜色为白色
#	然后通过写显存的方式,向ES:DI写入数据(PA_INDEX_WHITE)
draw_some_pixels:
	# 把索引1处的颜色改为白色(63,63,63)
	movw	$VIDEO_PALLETE_PORT,	%dx
	movb	$PA_INDEX_WHITE,		%al
	outb	%al,					%dx
	movw	$COLOR_SELECTION_PORT,	%dx
	movb	$63,					%al		# 红
	outb	%al,					%dx
	movb	$63,					%al		# 绿
	outb	%al,					%dx
	movb	$63,					%al		# 蓝
	outb	%al,					%dx

	# 设置ES的值
	movw	$VIDEO_SEG_GRAPHIC,		%ax
	movw	%ax,					%es

	# 设置要显示的像素位置的显存地址(目的地址)
	movw	$(800*5),				%di		# 从第五行像素开始开始
	movb	$PA_INDEX_WHITE,		%al
	movw	$800,					%cx		# 画800个连续像素即一条直线

draw_a_pixel:
	stosb
	#addl	$799,					%edi
	loop	draw_a_pixel

	ret

main:
	movw	%cx,	%ax
	movw	%ax,	%ds
	movw	%ax,	%es

	call	clear_screen					# 清屏
	call	set_video_mode_vbe_0x103		# 设置显示模式

	cmpw	$0,		%ax
	jne		1f
	call	set_video_mode_0x13
1:
	call	set_screen_bk_color	# 设置背景颜色
	call	draw_some_pixels	# 绘制像素

1:
	jmp		1b

# 常量定义:
	VIDEO_SEG_TEXT		= 0x0e00
	VIDEO_SEG_GRAPHIC	= 0xa000
	BUFFER_SEG			= 0x800

	VIDEO_PALLETE_PORT	= 0x3c8
	COLOR_SELECTION_PORT= 0x3c9
	
	MODE_0x13			= 0x13
	MODE_VBE_0x105		= 0x0105
	MODE_VBE_0x103		= 0x0103

	PA_INDEX_BACKGROUND	= 0x0
	PA_INDEX_WHITE		= 0x1

video_mode:
	.short	0
screen_x:
	.short	0
screen_y:
	.short	0
video_ram:
	.long	0

	.org	0x1fe,	0x90
	.word	0xaa55




评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值