自制操作系统05

今天VMware出问题了,可能是因为用的注册码过期了。于是换成了Oracle VM VirtualBox,用法查不多。不过我用的是5.2这个版本,6需要BIOS支持虚拟化。这个软件驱不是自动安装的,需要在设置里增加一下软驱。如下图:



结构体与指针的用法,我不记了,因为除了这本书,很多C语言书都有。
显示字符,也是一个像素一个像素显示的:
static char font_A[16] = {
    0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24,
    0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00
};
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;
}
putfont8(binfo->vram, binfo->scrnx, 10, 10, COL8_FFFFFF, font_A);

看到这我突然想明白了,图片/字符变成这种像素点的方法。首先图片需要是一个背景色为纯色的图片,然后就可以把它二值化了,二值化后,就可以形成如面那样的数组。最后显示每个像素,整个图/字符就出来了。
懂原理,实现就简单了,我就把我的头像转成下面这个样子,估计你的也差不多。


转换的时候要用到方差的算法,想想RGB的差值怎么来的。如果我再回到高中年代,我就会好好学习这部分知识了,可惜那时候不知道方差有什么用,也没学好。
作者为了显示字,整了上字库文件,还弄了个"编译器"把这个文件型成汇编的DB命令。哎,真是太麻烦了,高级语言绝不会这么干。
显示变量值,作者想把变量值显示到屏幕上,因为做操作系统没有debugger(调试器)可用。这与java线上出问题,而我们又不能debug,就只能打印日志是一样的道理。这个有用,那就把我的名字当变量在屏幕上显示一下吧。
strcpy(binfo->name,"zhong zhong");
sprintf(s, "@ %s", binfo->name);
putfonts8_asc(binfo->vram, binfo->scrnx, 16, 94, COL8_FFFFFF, s);
增加上面的几行代码即可显示出来。



显示鼠标,其实鼠标也是一个长方形的图片(像素点),不过除了鼠标的像素外,其他的颜色就是背景色。所以看起来就不是一个长方形图片了。不信咱们把鼠标的背景改成红色代码:
//init_mouse_cursor8(mcursor, COL8_008484);
init_mouse_cursor8(mcursor, COL8_FF0000);
void init_mouse_cursor8(char *mouse, char bc)
/* マウスカーソルを準備(16x16) */
{
    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;
}

效果就是这样了:


最后是GDT、IDT,为什么要讲这个,没这个鼠标就没法移动。
GDT: golbal Descrptor Table 全局段号记录表
IDT:Interrupt Descrptor Table    中断词记录表
要设置GDT的原因是,避免每个应用程序都需计算在内存的位置,所以把内存分成很多段。
要设置IDT的原因是,CPU的处理速度很快,为了不让CPU闲着,把键盘鼠标IO等事件放入中断记录表里,这样CPU就可以在1秒内处理很多事情。这样充分利用CPU,发挥它的计算能力。

文/中中 浏览次数:0次   2020-04-08 17:06:43

相关阅读


评论: