365bet亚洲版登录-bet官网365入口

365bet亚洲版登录拥有超过百间客房,bet官网365入口的文化历经几十年的传承和积淀形成的核心内容获得业界广泛的认可,365bet亚洲版登录是目前信誉最高的娱乐场所,同国内外几百家网上内容供应商建立了合作关系。

三十天自制操作系统

内部存款和储蓄器管理中分配内部存储器的函数即便提供了以字节为单位展开内存分配的函数,不过也大概会招致频仍分配内部存款和储蓄器和自由内部存款和储蓄器形成的产卓越多不总是的小段未采用的内部存款和储蓄器空间,那样会把内部存款和储蓄器清耗殆尽。所以又提供了三遍性分配和刑满释放解除劳教4KB内部存款和储蓄器空间的函数。

 unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size){ unsigned int a; size = (size + 0xfff) & 0xfffff000; a = memman_alloc(man, size); return a; }

要是要申请0x1005字节的内部存款和储蓄器,现论上大家理应给0x两千字节的内部存款和储蓄器,也便是发展舍入。依照日常的4舍5入的平整,这里应该供给动用除法和取余,可是此间运用了一个小技能,把低效的除法产生高效的与运算。

内部存款和储蓄器管理告一段落,以后要减轻从前鼠标移动时与画面叠合时出现的题材了。

为了缓慢解决窗口叠合、鼠标叠合的难题大家引进了图层的定义,最上边的小图层用来形容鼠标,中间描绘窗口,最下边描绘桌面。大家透过移到图层的方未法达成鼠标指针的运动,及窗口的运动。

先定义一个图层结构体

struct SHEET { unsigned char *buf;//图像缓存 int bxsize;//水平像素长度 int bysize;//坚直像素长度 int vx0;//水平方向起始点 int vy0;//坚直方向起始点 int col_inv;//颜色值,是否透明 int height;//该图层是第几层 int flags;//标记位,图层是否已被使用 };

把图层定义之后,然后定义操作系统的图层调控结构,在这一个结构体中定义操作系统最多管理2伍二十个图层。

struct SHTCTL { unsigned char *vram; int xsize, ysize, top; struct SHEET *sheets[MAX_SHEETS]; struct SHEET sheets0[MAX_SHEETS];};

概念完相关的数据结构之后,在主程序中开创S中兴TL实例,然后创立背景景图层和鼠标图层,把背景定义为第0层,鼠标为第1层。现在鼠标图层移到的时候,就能刷新整个画面。画面刷新的条条框框是那样的:先刷新第底下一层,再刷新上边一层,那样每便运动鼠标的时候,背景画面出会刷新,不会不复存在。

而是这样做纵然逻辑上和职能上都并没不寻常,首要是作用太低,每回移到鼠标都要刷新整个镜头,实际上鼠标移动时候借使刷新鼠标在此之前的那有个别和鼠标新的岗位那部分的镜头就行了,能够小幅提升功效。方法也极粗略,改变刷新函数,调用刷新函数的时候须求传入图层变化地方前的序幕地址,和调换后的最后全置就能够了。

看这一章特别要留意的荧屏的坐标和窗口座标的难点,很轻便弄混,小编这一章看了多少个礼拜。

看书来看这一步平时会对以前学过、通晓过的事物又生出嫌疑,又要不停得往回翻过来看。在看这一章小编运营程序的时候猛然见到鼠标是16*16像素的图象,为何一直不把前边的背景挡住,程序里是怎么落到实处的,从前好像从没怎么放在心上,然后又再次看了相关的次序。

跟鼠标相关的顺序有两有的,首倘若sheet.c里,还应该有graphic.c里面。

void init_mouse_cursor8(char *mouse, char bc){ static char cursor[16][16] = { "**************..", "*OOOOOOOOOOO*...", "*OOOOOOOOOO*....", "*OOOOOOOOO*.....", "*OOOOOOOO*......", "*OOOOOOO*.......", "*OOOOOOO*.......", "*OOOOOOOO*......", "*OOOO**OOO*.....", "*OOO*..*OOO*....", "*OO*....*OOO*...", "*O*......*OOO*..", "**........*OOO*.", "*..........*OOO*", "............*OO*", ".............***" }; int x, y; for (y = 0; y < 16; y++) { for (x = 0; x < 16; 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;}void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1){ int h, bx, by, vx, vy, bx0, by0, bx1, by1; unsigned char *buf, c, *vram = ctl->vram; struct SHEET *sht; if (vx0 < 0) { vx0 = 0; } if (vy0 < 0) { vy0 = 0; } if (vx1 > ctl->xsize) { vx1 = ctl->xsize; } if (vy1 > ctl->ysize) { vy1 = ctl->ysize; } for (h = 0; h <= ctl->top; h++) { sht = ctl->sheets[h]; buf = sht->buf; bx0 = vx0 - sht->vx0; by0 = vy0 - sht->vy0; bx1 = vx1 - sht->vx0; by1 = vy1 - sht->vy0; if (bx0 < 0) { bx0 = 0; } if (by0 < 0) { by0 = 0; } if (bx1 > sht->bxsize) { bx1 = sht->bxsize; } if (by1 > sht->bysize) { by1 = sht->bysize; } for (by = by0; by < by1; by++) { vy = sht->vy0 + by; for (bx = bx0; bx < bx1; bx++) { vx = sht->vx0 + bx; c = buf[by * sht->bxsize + bx]; if (c != sht->col_inv) { vram[vy * ctl->xsize + vx] = c; } } } } return;}

各个图层从最低层初阶刷新,最终边的桌面层未有安装透明,也等于col_inv设置为-1。将下来的每层,sheet_refreshsub函数总是先在刷新在此之前先拿走缓冲区像素颜色的值,然后把像素的颜色值为预先设置好的透明色比较,纵然想等那么那个像素就不会在荧屏上画,那么自色便是透明的。

这一节做了一个计数器,不停得在窗口中写入那符串,然后显示屏就闪烁了。首纵然由于sheet_refreshsub功用不高。其实就窗口上的字符在转移,不过刷新的时候从背景桌面开头从下至上全方位刷新了弹指间,大家要修改。

修改sheet_refreshsub函数,使之多接到二个参数h0表示变化的图层中最上边包车型地铁那一层,然后中间的基础代谢循环不从0最初,从h0开首。这样做之后即使品质进步了,但是依旧存在一些难点。

鼠标假使放置刷新的地点那么由于窗口会重新刷,鼠标就能够看起来一闪一闪的,最棒的艺术是鼠标所在的区域并非刷新,因为刷新未有用因为反正最终依旧被鼠标挡住的。

我们在内部存款和储蓄器中开荒一块和显示屏同样大的区域,大家称为显示屏地图,每一个内部存款和储蓄器单元做为二个像素点。然后每一次在活动图层的时候先往省外图中写入图层编号,然后每一次刷新显示器时候,先查询地图中的内部存款和储蓄器单元所存的数码是还是不是和该图层的编号,倘诺相等就刷新,假诺不等于就不刷新。其实这一个地图正是显示器的缓冲区。

这一章学习使用定时器。使用定时器只必要设置PIT,Programmable Interval Timer,翻译过来便是可编制程序的间隔型沙漏。设置了停车计时器,可以确反应计时器每隔多少秒就发出贰次中断,Computer中总是PIT的是IHighlanderQ0。

I奇骏Q0的中止周期更动

  1. al=0x34:out 0x43, al;
  2. al=中断周期的低8位;out 0x40 al;
  3. al=中断周期的高8位;out 0x40,al;

事实上中断发生的功效是主频/设定的数值。主频为1.壹玖叁壹8MHZ。因而若是我们把数值设置为11935的话,中断发生的功用也100Hz,也便是每10ms爆发三遍暂停,1一九三三折算成16进制相当于0x2e9c。

学会了运用机械漏刻,大家就能够完结超时功用了。所谓的晚点功用正是大家给系统设置三个时光,让系统在我们设置的光阴到了的时候通告CPU管理某种职分。举例大家能够如此设置:电火花计时器设器1秒,然后在历次时间达到的时候大家让显示屏上分钟向前走一秒。

概念超时成效采纳的数据结构

struct TIMERCTL { unsigned int count;//中断发生次数 unsigned int timeout;//设定的时间 struct FIFO8 *fifo;//定时器中断队列 unsigned char data;//数据 };

下面包车型地铁间歇管理程序

void inthandler20{ io_out8(PIC0_OCW2, 0x60); timerctl.count++; if (timerctl.timeout > 0) { timerctl.timeout--; if (timerctl.timeout == 0) { fifo8_put(timerctl.fifo, timerctl.data); } } return;}

停顿管理程序每回在timeout裁减到0时就向FIFO发送数据。见到此间作者发觉大家早就使用了三个种类,分别是鼠标音信队列,键盘音讯队列,坚持计时器音讯队列。难道每当中断大家都要使用三个音信队列,那样效能不高,又不便于程序维护,今后应该会把新闻队列合併的吗。

不菲情景下还索要安装 五个定时器。大家的靶子是最多能够设立500个沙漏,为了增加中断管理程序的效用,大家成立三个数据结构。

struct TIMER { unsigned int timeout, flags; struct FIFO8 *fifo; unsigned char data;};struct TIMERCTL { unsigned int count, next, using; struct TIMER *timers[MAX_TIMER]; struct TIMER timers0[MAX_TIMER];};

那边首要表达timers指针变量和timer0。后面一个是当真的沙漏结构体,保存了放大计时器的连带变量。后边贰个首借使用来电火花计时器超时的年华排序。

看一下停顿管理程序

void inthandler20{ int i, j; io_out8(PIC0_OCW2, 0x60); timerctl.count++; if (timerctl.next > timerctl.count) { return; } for (i = 0; i < timerctl.using; i++) { if (timerctl.timers[i]->timeout > timerctl.count) { break; } timerctl.timers[i]->flags = TIMER_FLAGS_ALLOC; fifo8_put(timerctl.timers[i]->fifo, timerctl.timers[i]->data); } timerctl.using -= i; for (j = 0; j < timerctl.using; j++) { timerctl.timers[j] = timerctl.timers[i + j]; } if (timerctl.using > 0) { timerctl.next = timerctl.timers[0]->timeout; } else { timerctl.next = 0xffffffff; } return;}

这段程序先判别下贰个过期的电磁打点计时器是还是不是过期,未有的话中断程序直接截至。借使下三个沙漏超时的话,寻觅最终多个过期的机械漏刻,并把最后三个过期的沙漏从前的装有计时器关闭,并向队列中发送消息。接下来把timers中的电火花计时器移位,并重复设置next数值。

安装电磁料理计时器的函数

void timer_settime(struct TIMER *timer, unsigned int timeout) { int e, i, j; timer->timeout = timeout + timerctl.count; timer->flags = TIMER_FLAGS_USING; e = io_load_eflags(); io_cli(); for (i = 0; i < timerctl.using; i++) { if (timerctl.timers[i]->timeout >= timer->timeout) { break; } } for (j = timerctl.using; j > i; j--) { timerctl.timers[j] = timerctl.timers[j - 1]; } timerctl.using++; timerctl.timers[i] = timer; timerctl.next = timerctl.timers[0]->timeout; io_store_eflags; return;}

在装置电火花计时器在此以前先关闭中断,然后找寻离将要设置的放大计时器超时时间最相仿的放大计时器所在地方,然后把那个电火花计时器向后移动,移动之后再插入这么些沙漏,就这么设置好了,而且timerctl中的放大计时器依然按超时时间不改变投放的。

本文由365bet亚洲版登录发布于计算机网络,转载请注明出处:三十天自制操作系统

您可能还会对下面的文章感兴趣: