30天自制操作系统日志第5天

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

操作系统实验日志学号20160810520姓名甘昆禄专业年级班级智能1601实验日期2018.10.24实验项目第5天:结构体、文字显示与GDT/IDT初始化一、实验主要内容1、接收启动信息和结构体在上一章中,xsize和ysize的值都是直接赋值为320*200,但实际上我们需要从asmhead.nas先前保存下来的值中去。即:不然的话,当画面模式改变时系统就不能正确运行。所以试着用指针取得图像模式:voidHariMain(void){char*vram;intxsize,ysize;short*binfo_scrnx,*binfo_scrny;int*binfo_vram;init_palette();/*设定调色板*/binfo_scrnx=(short*)0x0ff4;binfo_scrny=(short*)0x0ff6;binfo_vram=(int*)0x0ff8;xsize=*binfo_scrnx;ysize=*binfo_scrny;vram=(char*)*binfo_vram;for(;;){io_hlt();/*執行naskfunc里的_io_hlt*/}}诶这样是不是说就可以改变画面模式了?于是天真的我:保存运行一下,以为画面会显示坐标在左上角的320*200,结果发现画面显示错误,forgetaboutit。诶然后发现结构体里这个在汇编里没有定义,可能作者以后讲?哦先说结构体可以看做结构体是将一堆变量集中声明,然后作为新的变量用于其他场合。结构体的运用:(1)先声明结构体:如上图(2)后定义结构体变量:structBOOTINFOabc;或者定义结构体指针变量:structBOOTINFO*binfo;这里binfo表示指针变量后应该首先给指针赋值,可写成:Binfo=(structBOOTINFP*)0x0ff0;加上(structBOOTINFP*)是对数字进行强制类型转换,告诉编译器这个数字是一个BOOTINFO类型的指针变量。info指针指向地址0x0ff0是结构体的起始地址,结构体内的地址则依次按其类型增加。所以可以不用直接使用内存地址,而是使用*binfo来表示这个内存地址上12个字节的结构体。在表示结构体内变量的时候,使用“.”表示:xsize=(*binfo).scrnx;因为binfo是指向结构体地址的指针变量,它表示其内部变量的形式很多,可以用箭头表示:Xsieze=binfo-scrnx,或者用binfo-scrnx直接代替xsize2、显示字符终于到写字了,诶果然有定义好的哪个字母让具体哪个像素指定颜色,比如A的显示如下:用8x16的长方形像素点阵来表示,8位是一个字节,1个字符是16个字节,然后将字体主句写入主程序:staticcharfont_A[16]={0x00,0x18,0x18,0x18,0x18,0x24,0x24,0x24,0x24,0x7e,0x42,0x42,0x42,0xe7,0x00,0x00};程序里就会有A的信息了,当然放在程序里总是不好的,后面就有改了。显示字符的函数是这样:voidputfont8(char*vram,intxsize,intx,inty,charc,char*font){inti;char*p,d;/*data*/for(i=0;i16;i++){p=vram+(y+i)*xsize+x;d=font[i];if((d&0x80)!=0){p[0]=c;}//第i行的第1个像素,如果信息里存储的是1,就显示颜色Cif((d&0x40)!=0){p[1]=c;}if((d&0x20)!=0){p[2]=c;}if((d&0x10)!=0){p[3]=c;}if((d&0x08)!=0){p[4]=c;}if((d&0x04)!=0){p[5]=c;}if((d&0x02)!=0){p[6]=c;}if((d&0x01)!=0){p[7]=c;}}return;}这里就是将这个字符的16个字节用for循环逐个位判断,修改像素颜色,最终显示字符。然后再主函数中调用:putfont8(binfo-vram,binfo-scrnx,10,10,COL8_FFFFFF,font_A);运行结果如下:3、增加字体刚刚程序里只有字符A的信息,只能方便地显示A,那其他字符当然也要存啊,将平木敬太郎和圣人先生编辑好了的OSAKA字体(hankaku.txt)加入到源程序中,然后用工具(makefont.exe)将此文本读进来输出成16x256=4096字节的文件。编译后生成hankaku.bin文件,加上连接所必须的接口信息变成目标文件(bin2obj.exe来完成)。翻译之后相当于增加了此汇编语言:_hankaku:DB各种数据(共4096字节)然后像以前编译C语言写Makefile一样修改Makefile,加上相关代码。如果要在C语言中使用这种字体数据,只需要写上:Externcharhankaku[4096];像这种在源程序以外准备的数据,都需要加上externa属性。让编译器知道它是外部数据,并在编译时做出相应调整。OSASK的字体数据,依照一般的ASCⅡ字符编码,含有256个字符。A的字符编码是0x41,所以A的字体数据,放在“hankaku+0x41*16”开始的16字节里。C语言中A的字符编码可以用’A’来表示,正好可以用它来代替0x41,所以也可以写成“hankaku+’A’*16”。4、显示字符串和变量值在上一小节中,显示每次显示一个字母都会有这一句,比较繁琐:putfont8(binfo-vram,binfo-scrnx,8,8,COL8_FFFFFF,hankaku+'A'*16);像这种需要反复使用的语句,可以写成一个函数,再对此进行调用:函数需要的实际参数有binfo-vram,binfo-scrnx,8,8,COL8_FFFFFF,hankaku+'A'*16,对应于此设计函数的形参为:char*vram,intxsize,intx,inty,charc,unsignedchar*svoidputfont8_asc(char*vram,intxsize,intx,inty,charc,unsignedchar*s){externcharhankaku[4096];for(;*s1=0x00;s++){putfont8(vram,scrnx,x,y,c,hankaku+*s*16);x+=8;}return;}然后在主函数进行调用:voidHariMain(void){structBOOTINFO*binfo=(structBOOTINFO*)0x0ff0;init_palette();/*设定调色板*/init_screen(binfo-vram,binfo-scrnx,binfo-scrny);putfont8_asc(binfo-vram,binfo-scrnx,8,8,COL8_FFFFFF,ABC123);putfont8_asc(binfo-vram,binfo-scrnx,31,31,COL8_000000,HariboteOS.);putfont8_asc(binfo-vram,binfo-scrnx,30,30,COL8_FFFFFF,HariboteOS.);for(;;){io_hlt();/*執行naskfunc里的_io_hlt*/}}这里调用了三次,后面两次先显示的黑色,再在不同但临近坐标显示一次白色,达到立体效果。效果如下:然后这里作者说,要自制操作系统,现在就能自由显示变量很重要。因为这里没用debug可以用,如果出现错误就会很麻烦,就迫切需要知道变量有没有弄错。这里用到一个sprintf函数。sprintf函数和printf函数的区别在于它不是按指定格式输出,只是将输出内容作为字符串卸载内存中。sprintf函数的使用办法是:sprintf(地址,格式,值,值,值,……)这里的地址指定所生成字符串的存放地址。格式基本上只是单纯的字符串,如果有%的这类标记,就置换成后面的值的内容。除了%d(将数值作为十进制数转化为字符串)还有%s,%x(将数值作为十六进制转化为字符串)等符号。这里看来,sprintf函数的效果不过是将相应格式的内容存到相应地址罢了,要显示输出还是靠putfont8。5、显示鼠标指针显示指针跟显示字符思路一样,也是先准备16*16=256字节的内存,然后往里面写入指针的数据。将这个程序写在函数里面://绘制鼠标voidinit_mouse_cursor8(char*mouse,charbc)/*准备鼠标指针(16x16)*/{staticcharcursor[16][16]={**************..,*OOOOOOOOOOO*...,*OOOOOOOOOO*....,*OOOOOOOOO*.....,*OOOOOOOO*......,*OOOOOOO*.......,*OOOOOOO*.......,*OOOOOOOO*......,*OOOO**OOO*.....,*OOO*..*OOO*....,*OO*....*OOO*...,*O*......*OOO*..,**........*OOO*.,*..........*OOO*,............*OO*,.............***};intx,y;for(y=0;y16;y++){for(x=0;x16;x++){if(cursor[y][x]=='*'){mouse[y*16+x]=COL8_000000;}if(cursor[y][x]=='O'){mouse[y*16+x]=COL8_FFFFFF;}if(cursor[y][x]=='.'){mouse[y*16+x]=bc;}}}return;}课本说什么要将上面背景色显示出来,还要做下面这个函数,搞得我差点误解,看了半天,这个不就是将整个鼠标显示出来吗。这里分开的合理之处我猜应该是方便以后鼠标所到之处颜色的改变。voidputblock8_8(char*vram,intvxsize,intpxsize,intpysize,intpx0,intpy0,char*buf,intbxsize){intx,y;for(y=0;ypysize;y++){for(x=0;xpxsize;x++){vram[(py0+y)*vxsize+(px0+x)]=buf[y*bxsize+x];}}return;}主函数对鼠标显示函数的调用:voidHariMain(void){structBOOTINFO*binfo=(structBOOTINFO*)0x0ff0;chars[40],mcursor[256];intmx,my;init_palette();/*设定调色板*/init_screen8(binfo-vram,binfo-scrnx,binfo-scrny);mx=(binfo-scrnx-16)/2;//画面中央的坐标计算my=(binfo-scrny-28-16)/2;init_mouse_cursor8(mcursor,COL8_008484);putblock8_8(binfo-vram,binfo-scrnx,16,16,mx,my,mcursor,16);sprintf(s,(%d,%d),mx,my);putfonts8_asc(binfo-vram,binfo-scrnx,0,0,COL8_FFFFFF,s);for(;;){io_hlt();/*執行naskfunc里的_io_hlt*/}}显示结果:6、GDT和IDT的初始化(提及)让鼠标动起来需要将GDT和IDT初始化,他们都是与CPU有关的设定,是为了让操作系统能够使用32位模式,需要对CPU做各种设定。分段:打个比方就是按照自己喜欢的范式,将合计4GB的内存分成很多块(block),每一

1 / 13
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功