行业知识
30天自制操作系统(第23天)
2026-10-31 10:27:57
来源:互联网转载
23.1 编写malloc
参考���22天的内容,在绘制窗口前先分配了150*50个字节大小的内存,所以导致该文件经编译后有7.6k左右,能否在其中使用指针呢?当需要开辟空间时,移动指针即可。在之前的章节中也有函数memman_alloc函数可分配内存空间,所以在该节中将都用到这个函数。 按照下表对api的设计,编写a_nask.nas中的相关函数,以及增加console.c文件中对edx的判断。| memman 初始化 | malloc | free |
| EDX=8 EBX=memman 的地址 EAX=memman 所管理的内存空间的起始地址 ECX=memman 所管理的内存空间的字节数 | EDX=9 EBX=memman 的地址 ECX= 需要请求的字节数 EAX= 分配到的内存空间地址 | EDX=10 EBX=memman 的地址 EAX= 需要释放的内存空间地址 ECX= 需要释放的字节数 |
_api_initmalloc:; void api_initmalloc(void);PUSH EBXMOV EDX,8MOV EBX,[CS:0x0020] ; 初始化地址 P494页 0x0020 (DWORD) ……malloc空间的起始地址MOV EAX,EBX ADDEAX,32*1024;分配了32k内存MOV ECX,[CS:0x0000]SUBECX,EAX;包括前32位数据(文件信息)以及32k内存INT 0x40POP EBXRET_api_malloc:;char *api_malloc(int size)PUSHEBXMOVEDX,9MOVEBX,[CS:0x0020]MOVECX,[ESP+8];sizeINT0x40POPEBXRET_api_free:;void api_free(char *addr, int size)PUSHEBXMOVEDX,10MOVEBX,[CS:0x0020]MOVEAX,[ESP+8];addrMOVECX,[ESP+12];sizeINT0x40POPEBXRET
23.2 画点
该节实现绘制一个点的功能,下面先介绍一下API的设计: EDX =11 EBX = 窗口句柄 ESI = 显示位置的 x 坐标 EDI = 显示位置的 y 坐标 EAX = 色号/* a_nask.nas */_api_point:;void api_point(int win, int x, int y, int col);PUSHEDIPUSHESIPUSHEBXMOVEDX,11MOVEBX,[ESP+16];winMOVESI,[ESP+20];xMOVEDI,[ESP+24];yMOVEAX,[ESP+28];colINT0X40POPEBXPOPESIPOPEDIRET/* console.c */if(edx == 11){//api_pointsht = (struct SHEET *) ebx;sht->buf[sht->bxsize * edi + esi] = eax;//修改某个点的颜色sheet_refresh(sht, esi, edi, esi + 1, edi + 1);} 23.3 刷新窗口
考虑到每次绘制一个点都需要进行一次刷新,不如将所有点画好后刷新一次画面来的快,所以该节实现 刷新窗口的功能,下面先介绍一下API的设计: EDX = 12 EBX = 窗口句柄 EAX = x0 ECX = y0 ESI = x1 EDI = y1 如下操作:sht = (struct SHEET *) (ebx&0xfffffffe);的目的为,窗口句柄归根到底是struct SHEET的地址,这一定是一个偶数,所以使ebx为字符串的地址进行运算。ebx&1 == 0是判断ebx作为字符串的地址,是否为空,如果为空则刷新图层。/* a_nask.nas */_api_refreshwin:;void api_refreshwin(int win, int x0, int y0, int x1, int y1);PUSHEDIPUSHESIPUSHEBXMOVEDX,12MOVEBX,[ESP+16];winMOVEAX,[ESP+20];x0MOVECX,[ESP+24];y0MOVESI,[ESP+28];x1MOVEDI,[ESP+32];y1INT0X40POPEBXPOPESIPOPEDIRET/* console.c */int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax){(中略)if(edx == 1)cons_putchar(cons, eax&0xff, 1);else if(edx == 2)cons_putstr0(cons, (char*)ebx+ds_base);else if(edx == 3)cons_putstr1(cons, (char*)ebx+ds_base, ecx);else if(edx == 4) return &(task->tss.esp0); else if(edx == 5){(中略)}else if(edx == 6){/*这里*/sht = (struct SHEET *) (ebx&0xfffffffe);(中略)/*这里*/if(ebx&1 == 0)/*这里*/sheet_refresh(sht, eax, ecx, esi + 1, edi + 1);}else if(edx == 8){//memman初始化(中略)}else if(edx == 9){//malloc(中略)}else if(edx == 10){//free ecx = (ecx+0x0f)&0xfffffff0;//所释放的内存空间的字节数 memman_free((struct MEMMAN *) (ebx + ds_base), eax, ecx);}else if(edx == 11){//api_point/*这里*/ sht = (struct SHEET *) (ebx&0xfffffffe); sht->buf[sht->bxsize * edi + esi] = eax;/*这里*/ if(ebx&1 == 0)//当ebx的最低位为0,也就是没有字符串需要打印时,刷新图层/*这里*/sheet_refresh(sht, esi, edi, esi + 1, edi + 1);}else if(edx == 12){/*这里*/ sht = (struct SHEET *) ebx;/*这里*/ sheet_refresh(sht, eax, ecx, esi, edi);}return 0;} 23.4 画直线
在窗口上画直线: EDX = 13 EBX = 窗口句柄 EAX = x0 ECX = y0 ESI = x1 EDI = y1 EBP = 色号。考虑画的是直线,如果点间隙较大则会变成虚线,较小则会可能出现在一个坐标上多次花点浪费时间,所以选择将坐标跨度较大的间隙分为1024,直接看代码。/* a_nash.nas */_api_linewin:;void api_linewin(int win, int x0, int y0, int x1, int y1, int col);PUSHEDIPUSHESIPUSHEBPPUSHEBXMOVEDX,13MOVEBX,[ESP+20];winMOVEAX,[ESP+24];x0MOVECX,[ESP+28];y0MOVESI,[ESP+32];x1MOVEDI,[ESP+36];y1MOVEBP,[ESP+40];colINT0X40POPEBXPOPEBPPOPESIPOPEDIRET/* console.c */if(edx == 13){sht = (struct SHEET *) (ebx&0xfffffffe);hrb_api_linewin(sht, eax, ecx, esi, edi, ebp);if(ebx&1 == 0)//当ebx的最低位为0,也就是没有字符串需要打印时,刷新图层sheet_refresh(sht, eax, ecx, esi, edi);}void hrb_api_linewin(struct SHEET *sht, int x0, int y0, int x1, int y1,int col){int i, x, y, len, dx, dy;dx = x1-x0;dy = y1-y0;x = x0cur_c = COL8_FFFFFF;/*光标ON */if(i == 3)cons->cur_c = -1;/*光标OFF */if(256 clustno, finfo->size, p, fat, (char *) (ADR_DISKIMG + 0x003e00));if (finfo->size >= 36 && strncmp(p + 4, "Hari", 4) == 0 && *p == 0x00){(中略)start_app(0x1b, 1003 * 8, esp, 1004*8, &(task->tss.esp0));/*从这里开始*/shtctl = (struct SHTCTL *) *((int *) 0x0fe4);/*从这里开始*/for(i = 0; i sheets0[i]);if(sht->flags != 0 && sht->task == task)sheet_free(sht);/*到这里结束*/}memman_free_4k(memman, (int) q, segsiz);}elsecons_putstr0(cons, ".hrb file format error.\n");memman_free_4k(memman, (int) p, finfo->size);cons_newline(cons);return 1;}return 0;}()()
下一篇:忍三怎么看服务器?