[读书笔记]30 天自制操作系统 day5 结构体, 文字显示与GDTIDT初始化

    xiaoxiao2021-12-14  18

    1. 接收启动信息

    采用结构体, 将各个独立的变量联系起来, 让程序有更好的可读性 原始未使用 结构体的代码: void HariMain(void) { char *vram; int xsize, 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; init_screen(vram, xsize, ysize); for (;;) { io_hlt(); } }

    使用了结构体之后的代码 明显代码的可读性提高了好多

    struct BOOTINFO { char cyls, leds, vmode, reserve; short scrnx, scrny; char *vram; }; void HariMain(void) { struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0; init_palette(); init_screen(binfo->vram, binfo->scrnx, binfo->scrny); for (;;) { io_hlt(); } }

    4. 显示字符

    之前显示字符使用的是 BIOS 中断, 现在cpu 处于 32 bit 模式, 需要手工绘制图形

    通过将指定字符数据写入 VRAM 空间中, 实现字符的显示

    void putfont8(char *vram, int xsize, int x, int y, char c, char *font) { int i; char *p, d /* data */; for (i = 0; i < 16; i++) { p = vram + (y + i) * xsize + x; d = font[i]; if ((d & 0x80) != 0) { p[0] = c; } if ((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; }

    字体数据

    static char font_A[16] = { 0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00 };

    5. 增加字体

    这里采用的是OSASK 字体, 并通过在 MAKEFILE 中使用 makefont 编译字体文件得到字体数据

    封装字符串

    void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s) { extern char hankaku[4096]; for (; *s != 0x00; s++) { putfont8(vram, xsize, x, y, c, hankaku + *s * 16); x += 8; } return; }实现效果

    6. 显示变量值

    通过sprintf 函数将变量值写入到字符串中

    8. 显示鼠标

    本质上就是读入鼠标cursor 的字符数组, 根据其中的字符将相应的vram 中的某个内存的数据设置成调色板中的某个标号, 来显示相应的字符。

    9. GDT 和 IDT 的初始化

    这里采用分段内存管理, 段寄存器表示 段的起始地址段需要有以下信息 段的大小段的起始地址段的管理属性但是, cpu的段寄存器只有16bit, 那么可以模仿调色板的做法, 建立段寄存器与段号之间的一种映射关系, 由于段寄存器德尔低三位表示权限, 可以使用的只有13bit, 因而, 可以处理 0 ~ 8191 的区域 (64KB)这个就是我们的 GDT(全局段号记录表)IDT 是中断记录表 为了处理外设的各种事件, 一般可以采用轮询方式, 不过轮询的频率不好控制, 太慢, 外设得不到响应, 太快, cpu做无意义处理, 因而, 一般采用 中断方式本质上相当于, 将监控外设的任务委托给了第三方对象, 让第三方对象负责处理监控事件, 然后cpu专心处理手头的任务, 也可以理解成 cpu 请了一个小蜜
    转载请注明原文地址: https://ju.6miu.com/read-969161.html

    最新回复(0)