30天自制操作系统------图形处理相关

来源:互联网 发布:怎么找放单的淘宝商家 编辑:程序博客网 时间:2024/06/09 16:20

一、编写malloc

每个应用程序至少都需要一个窗口,窗口的内容需要保存在一块内存中,我们原来的做法是使用固定大小的数组如buf[320*200],然后往里面填写东西,但是这样子的后果就是应用程序的.hrb文件比较大,使用二进制文件打开.hrb文件发现里面有很多“00”。原因就是数组的声明就相当于汇编中的RESB指令,在内存中给为数组预留出了数组所需要的空间。

为了减小.hrb的大小,我们需要编写malloc函数,虽然说以前已经有一个memman_alloc函数,但是因为memman_alloc函数分配的内存空间并不位于应用程序的数据段范围内,所以我们需要编写一个为应用程序分配内存空间的API函数,然后将malloc的内存空间的首地址写到.hrb文件当中去,这样就可以有效减少.hrb文件的大小。

malloc函数若想要实现分配内存的功能,那么操作系统就需要提前给应用程序预留一定大小的空间用于malloc,因为应用程序所需要的内存空间无法预测,最好的做法是用于给malloc函数分配的内存空间可以调整大小,但是在我们自制的操作系统中没有实现这样的功能,只能给malloc函数预留一定大小的空间,这也算是一个需要优化的地方。

当然malloc函数还是需要对应的free函数。

 

编写API函数malloc的思路:

(1)使用memman_init函数初始化一个memman,参数中的地址要写应用程序段的地址;

(2)使用memman_free函数释放空间,为应用程序的malloc预留这段空间;

(3)使用memman_alloc函数为应用程序分配空间;

(4)应用程序结束时使用memman_free函数释放空间。

     虽然memman_initmemman_allocmemman_free这几个函数都只能在操作环境下使用,但是还是可以通过API的方式来进行调用。

 

二、画点/画线

每个任务都要有个窗口,也就是说每个任务都要有占用一个图层,想要在任务的界面上显示一些内容,只需要在对应的图层的buf中填写相应的内容,然后刷新图层即可。图层SHEET的定义如下:

struct SHEET{unsigned char *buf;  /*用来记录图层上所描画内容的地址*/int xsize,ysize,x,y,color,height,flags;struct SHTCTL *ctl;}; 

 (1)若要在窗口上显示一个点,那么就在对应图层的buf中修改一个单元的内容即可。

 2)若要在窗口上显示多个点,那么就在对应图层的buf中修改多个单元的内容即可。

 3)点动成线,可以画点就可以画线,两点确定一条直线,只要确定了线的起点坐标和终点坐标,就可以画出这条线。

画线的思路:

设起点(x0,y0终点(x1,y1

         ①求横纵坐标的差值:dx=x1-x0,dy=y1-y0

         ②求横纵坐标差值的绝对值:dx=|dx|,dy=|dy|

         ③比较dxdy,确定点的个数len

        a.dx>=dylen=dx+1dx=1dy=dy/len,若x0<x1dx=-dx,若y0<y1dy=-dy

        b.dx<dylen=dy+1dy=1dx=dx/len,若x0<x1dx=-dx,若y0<y1dy=-dy

         ④ x=x0y=y0  

     按如下方式画len个点:画点(x,y),x+=dxy+=dy


三、关闭窗口

    应用程序结束之后其窗口应该关闭,一直留在桌面也不好看。

应用程序的窗口都对应一个图层,要想关闭应用程序的窗口,只需要将其所对应的图层的内存所释放即可,之前编写sheet.c时就有一个实现此功能的函数sheet_free(),我们只需要在API函数api_closewin中调用该函数即可。

想要实现按下某个键任务窗口关闭的功能,我们需要API实现如下功能get_key(),返回值为按键编码:

我们使用汇编语言编写该函数,在该函数中使用INT 0x40调用API,所以获取按键编码的工作实际上是hrb_api函数完成的。

hrb_api函数为该功能分配的功能号为1515号功能的工作原理如下

   1)改造TASK的结构,为其增加一个FIFO成员,如下:

    

struct TASK{int sel,flags;  /*sel用来存放GDT的编号*/int level;int priority;/*优先级*/struct FIFO fifo;struct TSS tss;};

   2)让TASKFIFO来接收数据

   3)若FIFO为空,任务休眠

   4)若FIFO不为空,取出FIFO中的数据,对不同的数据做出不同的处理,若是键盘输入的数据,将按键编码返回,作为get_key()函数的返回值。

按照以上思路来编写应用程序时,程序结束之前会进入死循环,每次都判断get_key()的结果,判断它是否是我们指定的按键编码,若是则跳出循环,关闭窗口。

 

 

四、强制结束并关闭窗口

第三部分解决的是正常关闭窗口的思路,但是在强制结束任务时,窗口还是不会关闭。应用程序时在cmd_app函数中通过start_app来启动的,当应用程序执行完毕之后或者被强制结束后都会返回到cmd_app中执行start_app后的程序,利用这一点,我们可以在start_app调用结束后,释放任务对应的图层所使用的空间。

为了能将TASKSHEET对应,我们在SHEET中又添加了TASK成员,添加之后的SHEET结构如下:

 

struct SHEET{unsigned char *buf;  /*用来记录图层上所描画内容的地址*/int xsize,ysize,x,y,color,height,flags;struct SHTCTL *ctl;struct TASK *task; /*该图层的任务*/ }; 

在生成新的窗口时将对应的图层和任务进行绑定,在结束任务时,将任务对应的图层的内存进行释放即可。



原创粉丝点击