ImageVerifierCode 换一换
格式:DOCX , 页数:17 ,大小:45.09KB ,
资源ID:30170078      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/30170078.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(做一个支持图形界面的操作系统上.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

做一个支持图形界面的操作系统上.docx

1、做一个支持图形界面的操作系统上做一个支持图形界面的操作系统(上)副标题:作者:谢煜波 文章来源:本站原创 点击数: 713 更新时间:2004-9-18(转载及引用请注明明原作者及出处)(pdf: (源代码:做一个支持图形界面的操作系统(上)Version 0.01(对应pyos版本号:2004_09_18_14_00)哈尔滨工业大学 谢煜波(email:xieyubo 网址:)(QQ:13916830 哈工大紫丁香BBSID:iamxiaohan)前言 图形界面(GUI)几乎被现在所有的主流操作系统及应用程序使用,这是因为它提供了极好的人机交互接口,微软大名鼎鼎的Windows就是一个非常成

2、功而明显的例子,据说微软的理念有一条就是“让电脑变得越来越傻瓜,任何人都可以操作它”,很显然,要实现这个梦想,GUI界面是必须的。 如果有操作系统的支持,编写具有图形界面的程序是一件相对来说比较容易的事情,因为操作系统为你管理显卡,为你提供了各种各样诸如画点、画线、画矩形、填充等各种图形函数,你只需要将你所希望显示的东西,通过直接调用这样一些函数生成就行了,操作系统会为你完成余下的一切。 然而,如果你打算自己从头编写一个操作系统,而没办法使用已有的操作系统所提供的便利功能的时候,又应当怎样完成这样一个图形界面呢? 本文打算继续以pyos系统为例,简单描述一下怎样让你自己的操作系统支持图形界面。

3、如果你想更好的理解本篇的内容,你需要对操作系统的引导过程有些许了解,这可以参考一下本文的参考文献1,另外,你还需要对汇编语言有所了解,这可以参考一下本文的参考文献2。本文的实验代码由汇编及C语言完成,如果你对C语言不太了解,可以参考一下本文的参考文献3。 标准的GUI界面应当包括图形化界面的显示及对用户输入的支持,而现在在GUI界面下用的最广泛的用户输入设备就是鼠标了。因此本文打算以两部份分别进行描述。上篇描述图形界面的显示,下篇描述对鼠标的支持。 由于知识及水平所限,对于其中不当及错误之处或者您有任何建议,非常欢迎您与我联系。我会在哈工大纯C论坛上()上对本文进行跟踪反馈,本文所描述的资料及

4、源代码也可以在上面找到。一、显卡接口标准VESA简介 所谓标准,其实就是一种协议,比如显卡接口标准,就是显卡与主机之间进行通信的协议,通过这个协议,主机就能操作及控制显卡。比如主机要让显卡在(x,y)画一个点,需要对显卡进行什么操作,这在协议上都有明确的说明与规定,因此,如果我们要操作一个显卡,只需要按照协议上的说明与规定进行就行了,这里的协议就如同一个说明书一样。 随着显卡的发展,先后出现了很多种协议,比如EGA协议,CGA协议,VGA协议等,而现在用得最广泛的是由国际视频电子标准协会(Video Electronics Standards Association)制定的称为VESA的协议,

5、现在最新的协议版本是3.0,不过由于目前并不是所有的显卡均支持此项协议,特别是众多的虚拟机都不支持,因此本文将以2.0版本作为描述的基础,由于各版本是向下兼容的,因此基于2.0的程序完全可以不经修改的应用在3.0版本上。 VESA标准包括了很多的子标准,其中对于操作系统编写最有用的就是VBE标准(Vesa Bios Extension),在实际的系统编写中,我们按照此标准,通过调用BIOS的0x10号中断,而对显卡进行操作,在调用此号中断的时候,ax寄存器中存放的就是你想使用的显卡的功能。比如VESA 2.0标准规定:0x4F00号功能可以返回显卡所支持的VESA标准的信息,0x4F01号功能

6、可以返回所指定的显示模式的信息,诸如行列像素是多少,每像素的字节数是多少之类。调用这些功能是非常方便的,比如,通过阅读VESA标准,我们知道0x4F02号功能可以用来设置显示模式,调用此功能时,bx中存放的是欲设置的显示模式的编号,因此,如果我们想将显卡的显示模式设为0x111模式,那么我们应当编写如下的代码: mov ax , 0x4F02 ;设置中断功能号,表示使用0x4F02号功能 mov bx , 0x111 ;设置显示模式号,表示使用0x111显示模式 int 0x10 ;调用BIOS的0x10号中断,设置显卡功能 执行了上面的代码之后,显卡就被设置成了0x111号显示模式,那么这个

7、模式有些什么显示特性呢?请看下面的表格:(表1 VESA标准定义的显示模式(部份)模式号分辨率色彩0x100640*4002560x101640*4802560x102800*600160x103800*6002560x1041024*768160x1051024*7682560x1061280*1024160x1071280*10242560x10D300*2001:5:5:50x10E320*2005:6:50x10F320*2008:8:80x110640*4801:5:5:50x111640*4805:6:50x112640*4808:8:80x113800*6001:5:5:50x1

8、14800*6005:6:50x115800*6008:8:80x1161024*7681:5:5:50x1171024*7685:6:50x1181024*7688:8:80x1191280*10241:5:5:50x11A1280*10245:6:50x11B1280*10248:8:8 上面的表格列出了VESA标准所定义的部份显示模式,其中色彩有两种表示形式。一种是所谓的“调色板”模式,一种是所谓的“真彩”模式,“调色板”模式主要是为了兼容以前的老式显卡,那种显卡上的显存数量一般说来都非常的少,因此,显卡上一次最多只能存储256种(8位)或更少的16种色彩(4位),比如本表前面部份所示。

9、显卡上把这些色彩组织成为一个表,这个表就称之为一个调色板,然后每点的色彩信息其实就是一个下标,用于从调色板中检索出真正的色彩。比如一个点的色彩是2,则表示使用调色板中的第三个色彩(因为从0开始编号,所以2则对应调色板中第三项)。很显然,不是所有的色彩都能被记录在小小的调色板中,因此一般说来,对于一种给定色彩,我们需要用调色板中与它最相近的色彩进行显示。 现在的显卡一般都有很大的显存,因此它可以完整的存放一个点的色彩信息。我们知道,任何一种色彩都可用不同强度(亮度)的红(R)、绿(G)、兰(B)三种色彩合成,因此,我们要记录或给出一个点的色彩信息,只需要给出红、绿、兰这三种色彩各自的强度(亮度)

10、就行了,因此,就出现了多种不同的编码方法,比如“5:6:5”模式,就表示用最高的5位表示红色的强度,用中间的6位,表示绿色的强度,用最后的5位表示兰色的强度,这样表示一个色彩,总共需要16位,即2B,而“8:8:8”则表示,最高的8位表示红色的强度,随后的8位,表示绿色的强度,最后的8位表示兰色的强度,一个色彩用24位,即3字节进行表示。依次类推。由于这些色彩都被真实的记录下来了,因此这种模式又被称为“真彩”模式,如表1的后面部份所示。 由上面描述可知,我们可以根据我们的需要,选择适当的显示模式,然后调用VBE标准中所定义的中断设置显示卡。 VBE标准描述了大量的功能,这里不打算将它全部描述,

11、只介绍下面行文所需要的功能,如果你想了解整个VBE标准所描述的功能,请参考本文的参考文献4。 下面我们再描述一个下面需要用到的0x4F01功能。这个功能可以把显卡所支持的显示模式的对应信息返回到用户所指定的地址中。它可以如下调用: mov ax , 0x4F01 ;表示使用 0x4F01 功能,以获得显示模式信息 mov cx , 0x111 ;表示欲获得0x111显示模式的信息 mov es , 0x9000 mov di , 0x0001 ;上面两句表示把信息放在es:di;(此处为0x9000:0x0001)处,这是一块内存的;起始地址,而此块内存至少256B大小返回的信息是一个256字

12、节的,很庞大的结构,这里我们只介绍我们下面行文感兴趣的部份。在返回的结构体中偏移量为40的地方,即es:di+40处,用4字节存放了一个线性地址,这就是这个显卡在此模式下显存的线性地址,因此,如果我们直接向这个地址写入数据,那么这数据就会被直接写到显存上,这样就可以显示出我们所需要显示的信息了。这就是所谓的“直接写屏”。 返回的结构体中还包括了该显卡在此模式下每行行像素,列像素等其它众多信息,如果你需要详细了解,请参看本文的参考文献4。二、用Pyos进行实验2.1 引导代码分析 令人非常高兴的是,这次实验我们不需要了解太多的基础知识,而就可以很快的进入实验了,下面我们就来看看我们这次的实验。

13、在实验前,我们需要先设定一个我们需要实验的显示模式,这里我们暂且定为640*480,采用的色彩模式为5:6:5模式,即0x111模式。 我们先来看看我们这次实验的最终结果:现在,让我们先来看看我们的引导代码:main: ;主程序 ;下面设置段寄存器 mov ax , BOOT_SEG mov ds , ax mov ax , TEMP_DATA_SEG mov ss , ax mov sp , 0xffff mov BOOT_DRIVER , dl ;得到启动的驱动器号 call open_a_20 ;打开 a20 地址线 call save_boot_driver ;保存驱动器号 call

14、show_message ;显示启动信息 call read_setup ;读入 setup 程序 jmp dword SETUP_SEG:SETUP_OFFSET ;跳转到 setup 处执行 这是pyos引导程序(boot.asm)的主函数代码,它现在已经很简单了,最开始,你需要设定一下段寄存器,比如初始化一下数据段寄存器(DS),堆栈段寄存器(SS),及堆栈指针(SP)等,然后,通过read_setup这个子程序,读入setup程序(steup.asm),将其读到SETUP_SEG:SETUP_OFFSET处(SETUP_SEG及SETUP_OFFSET都是在boot.asm最开头定义的

15、常量),关于各子程序的详细代码,请参看本实验的源代码,其中均有很详尽的注释。 下面,让我们看看setup(setup.asm)程序:main: ;初始化寄存器,因为 Bios 中断及 call 会用到堆栈或 ss 寄存器 ;在 CPU 启动或复位时是由 BIOS 初始化的,而现在进行了段转移,需要我们重新设置 mov ax , SETUP_SEG mov ds , ax mov ax , TEMP_DATA_SEG mov ss , ax mov sp , 0xffff ;显示启动信息 call show_message ;取得启动驱动器号 call get_boot_driver ;设置显示

16、模式 call set_vesa_model ;读入 kernel 程序 call read_kernel ;读入字库 call read_font_lib ;读入 hit 的图片 call read_hit_pbmp ;下面开始为进入保护模式而进行初始化工作 lgdt gdt_descriptor ;载入gdt的描述符 ;下面设置进入32位保护模式运行 cli ;关中断 mov eax , cr0 or eax , 1 mov cr0 , eax jmp dword 0x8:KERNEL_ENTRY 上面这段程序也是非常简单的,首先,重新初始化一下段寄存器,然后设置图形显示模式,之后,读入k

17、ernel程序(这是真正的操作系统的内核代码),然后再读入字库(这点在下面会有较为详尽的描述),随后再读入一张hit的图片(hit是“哈尔滨工业大学”的英文缩写,图片采用的是一种bmp格式,这在下面也会有详细描述),之后进行转换到保护模式下的工作,最后切换到保护模式下的kernel程序处,即真正的操作系统内核代码中执行。有关这部分切换到保护模式下的工作,本文的参考文献1中有非常详细的描述,如果你对此部份有疑惑,可以参看一下。下面我们来看看这次的核心子程序set_vesa_model的代码,其余代码请参看本实验的源程序。set_vesa_model: ;设置显卡模式 push es push f

18、s ;设置显卡模式 mov ax , 0x4f02 mov bx , 0x4111 ;640 * 480 ( 5:6:5 ) int 0x10 ;取得该模式下显存线性地址 mov bx , SETUP_SEG mov es , bx mov di , VESA ;调用0x4F01功能号,获得信息 mov ax , 0x4f01 mov cx , 0x111 int 0x10 ;存入线性地址 mov eax , es:VESA + 40 mov bx , TEMP_DATA_SEG mov fs , bx mov fs:1 , eax pop es pop fs ret 程序非常简单,下面简单的

19、解释一下,进入程序后,我们最先就设置了显卡的显示模式: ;设置显卡模式 mov ax , 0x4f02 mov bx , 0x4111 ;640 * 480 ( 5:6:5 ) int 0x10 上面这几行代码在前面描述VBE标准时就介绍过了,这里我们设置的是640*480(5:6:5),即对应的0x111模式(见表1),不过,你会发现这里送入bx的是0x4111而不是0x111,这是为什么呢?这主要是因为,我们要使用线性地址模式,也就是说通过直接访问物理内存空存来访问所有的显存空间,因此,这时的送入bx的就应当是0x4000|模式号,对于此处就是:0x4000 | 0x111 = 0x411

20、1(将模式号与0x4000进行与操作,这也是VBE标所规定的)。 随后,我们用0x4F01功能取得此模式下显卡显存的线性地址: ;取得该模式下显存线性地址 mov bx , SETUP_SEG mov es , bx mov bx , TEMP_DATA_SEG mov fs , bx mov di , VESA ;调用0x4F01功能号,获得信息 mov ax , 0x4f01 mov cx , 0x111 int 0x10 上面由于 es = TEMP_DATA_SEG,di = VESA,所以读取出来的信息存放于TEMP_DATA_SEG:VESA处,随后,从信息中取出显卡在此模式下显存

21、的线性地址: ;存入线性地址 mov eax , es:VESA + 40 mov bx , TEMP_DATA_SEG mov fs , bx mov fs:1 , eax pop es pop fs ret 上面代码很简单,由于显卡在此模式下显存的线性地址是存在于返回的信息块中偏移量为40之处,所以,用“mov eax , es:VESA + 40 ” 从中读取到eax中,然后,再把其放入 fs:1 处,由于fs等于TEMP_DATA_SEG,所以,是存放在了TEMP_DATA_SEG:1处。 上面程序中的 SETUP_SEG , VESA , TEMP_DATA_SEG都是在程序最初所定

22、义的常量,详情请参看源代码。2.2 pyos 内存结构由于本实验的pyos还没有文件系统及内存管理与分配程序,因此,在本实验中,pyos采用的是磁盘及内存的绝对定位,即所有数据在内存中的位置都是固定的,下面就让我们来看看 pyos 的内存结构。0x0000:0x7c00 :此处存放的是boot.asm的代码,由系统加电时BIOS自动读入0x1000:0x0000 :此处存放的是setup.asm的代码,由boot.asm读入0x2000:0x0000 :此处存放的是内核代码(主要是kernle.c),由setup.asm读入0x6000:0x0000 :此处存放的是hit的图片数据,由setu

23、p.asm读入0x7000:0x0000 :此处存放的是英文点阵字库数据,由setup.asm读入0x8000:0x0000 :此处存放的是中文点阵字库数据,由setup.asm读入0x9000:0x0000 :此处存放的是启动驱动器号,由boot.asm存入0x9000:0x0001 :此处存放的是显卡显存的线性地址2.3 pyos 图形驱动在程序由setup.asm最后通过“jmp dword 0x8:KERNEL_ENTRY”跳入内核代码之后,操作系统开始正式运作,下面就让我们来看看这个内核代码:#include system.h#include vesa.hvoid kernel_ma

24、in() / 系统初始化 system_init() ; / 清屏 unsigned short color = vesa_compond_rgb( 255 , 255 , 255 ) ; / 画矩形 vesa_draw_rect( 0 , 0 , 639 , 479 , color , 1 ) ; (其余画图代码略) for( ; ) ; 上面的代码非常简单,它首先进行了一下系统初始化,然后进行清屏,pyos清屏采用的是最蜗牛的一种办法,它把整个屏幕当做一个矩形(x:0639,y:0479),然后用一种色彩去画这个矩形中的每一个点。vesa_compond_rgb()这个函数用于把用户输入的

25、R(红),G(绿),兰(B)值合成为一个16位长的整数(因为采用的是5:6:5的模式,因此总共一个点的色彩用16位整数表示),然后,它调用了vesa_draw_rect()函数来画这个矩形,我们就来看看这个函数:/ 画矩形函数void vesa_draw_rect( unsigned int x1 , unsigned int y1 , unsigned int x2 , unsigned y2 , unsigned short color , int dose_fill_it ) vesa_draw_x_line( y1 , x1 , x2 , color ) ; vesa_draw_x_l

26、ine( y2 , x1 , x2 , color ) ; vesa_draw_y_line( x1 , y1 , y2 , color ) ; vesa_draw_y_line( x2 , y1 , y2 , color ) ; if( dose_fill_it ) vesa_fill_rect( x1 , y1 , x2 , y2 , color ) ; 非常简单,它首先画矩形的边框,然后,根据用户的输入参数决定是否调用vesa_fill_rect()函数对这个矩形进行填充。下面我们就来看看这个填充函数:/ 矩形填充函数void vesa_fill_rect( unsigned int x

27、1 , unsigned int y1 , unsigned int x2 , unsigned int y2 , unsigned short color ) for( int x = x1 ; x x2 + 1 ; +x ) for( int y = y1 ; y x_max ) x = x_max ; if( y y_max ) y = y_max ; / 取得显存线性地址 unsigned short *video = ( unsigned short * )( * ( ( unsigned int *)0x90001 ) ) ; / 计算点的偏移量 unsigned int offs

28、et = y * ( x_max + 1 ) + x ; *( video + offset ) = color ;这个函数是整个Pyos VESA显卡驱动的根基,所有画线、画矩形、填充矩形都是由它完成的,现在我们就来分析一下,注意下面的一行代码: / 取得显存线性地址 unsigned short *video = ( unsigned short * )( * ( ( unsigned int *)0x90001 ) ) ; 首先,在2.2节中我们知道了0x9000:0001处存放了显卡显存的线性地址(这个线性地址是32位,即4B),因此,把0x9000:0001转换为线性地址就是0x90001,然后,我们在C语言中把它转强行转换成一个指向unsigned int型的指针,然后通过 * 操作符,取出了这个指针,即地址为0x90001处所存的数据,也就是取得了存放于此处的显存的线性地址,然后把它强性转换为一个unsigned short型的指针,这是因为,每个点都是用2B字节,也就是都是用一个unsigned short类型的数据表示的,这个线性地址也是(0,0)点的地址。 随后,我们通过列坐标:x,行坐标:y,算得了(x,y)点的偏移量,最后直接把色彩信息赋值给这个(x,y)点所在的内存地址,那么(x,y)点处就显现出了我们

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1