30天自制操作系统读书笔记(四)

想要在画面里画点什么东西,就需要往VRAM的内存区里写入点什么东西。

但是如何写入呢?

作者先用了汇编:

         _write_mem8:         ; void write_mem8(int addr, int data);

                   MOV                  ECX,[ESP+4]               ; [ESP + 4]中存放的是地址,将其读入ECX

                   MOV                  AL,[ESP+8]                 ; [ESP + 8]中存放的是数据,将其读入AL

                   MOV                  [ECX],AL

                   RET

SP是指向栈的指针,C语言压入参数又是从右往做压的,而压栈又是高地址压入低地址,而32位一次入栈就是4个字节。所以自然而然,[ESP+4]的内容就是地址,+8那就是数据了。

下面的一些C语言代码我就省略了。

作者的第二个方法是使用指针。我觉得C语言的指针还是应该去好好了解的,建议看一下

《C和指针》这本书。

至于什么调色板,想来也是十分好理解。

因为设定调色板的时候要屏蔽中断,但是设定好了又要回复,所以作者写了2个函数,先屏蔽在回复。

哦,实在不想赘述太多,因为这一章没有啥新概念,单纯的一些C语言罢了。

直接上代码吧。

void io_hlt(void);
void io_cli(void);
void io_out8(int port, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);

void init_palette(void);
void set_palette(int start, int end, unsigned char *rgb);
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);

#define COL8_000000        0
#define COL8_FF0000        1
#define COL8_00FF00        2
#define COL8_FFFF00        3
#define COL8_0000FF        4
#define COL8_FF00FF        5
#define COL8_00FFFF        6
#define COL8_FFFFFF        7
#define COL8_C6C6C6        8
#define COL8_840000        9
#define COL8_008400        10
#define COL8_848400        11
#define COL8_000084        12
#define COL8_840084        13
#define COL8_008484        14
#define COL8_848484        15

void HariMain(void)
{
    char *p; /* pという変数は、BYTE [...]用の番地 */

    init_palette(); /* パレットを設定 */

    p = (char *) 0xa0000; /* 地址赋值 */

    boxfill8(p, 320, COL8_FF0000,  20,  20, 120, 120);
    boxfill8(p, 320, COL8_00FF00,  70,  50, 170, 150);
    boxfill8(p, 320, COL8_0000FF, 120,  80, 220, 180);

    for (;;) {
        io_hlt();
    }
}

void init_palette(void)
{
    static unsigned char table_rgb[16 * 3] = {
        0x00, 0x00, 0x00,    /*  0:黒 */
        0xff, 0x00, 0x00,    /*  1:明るい赤 */
        0x00, 0xff, 0x00,    /*  2:明るい緑 */
        0xff, 0xff, 0x00,    /*  3:明るい黄色 */
        0x00, 0x00, 0xff,    /*  4:明るい青 */
        0xff, 0x00, 0xff,    /*  5:明るい紫 */
        0x00, 0xff, 0xff,    /*  6:明るい水色 */
        0xff, 0xff, 0xff,    /*  7:白 */
        0xc6, 0xc6, 0xc6,    /*  8:明るい灰色 */
        0x84, 0x00, 0x00,    /*  9:暗い赤 */
        0x00, 0x84, 0x00,    /* 10:暗い緑 */
        0x84, 0x84, 0x00,    /* 11:暗い黄色 */
        0x00, 0x00, 0x84,    /* 12:暗い青 */
        0x84, 0x00, 0x84,    /* 13:暗い紫 */
        0x00, 0x84, 0x84,    /* 14:暗い水色 */
        0x84, 0x84, 0x84    /* 15:暗い灰色 */
    };
    set_palette(0, 15, table_rgb);
    return;

    
}

void set_palette(int start, int end, unsigned char *rgb)
{
    int i, eflags;
    eflags = io_load_eflags();    /* 用来保存当前flag寄存器的信息 */
    io_cli();                     /* 屏蔽中断 */
    io_out8(0x03c8, start);   //IO_OUT8 作用不详,作者的意思说,以后在进行解释
    for (i = start; i <= end; i++) {
        io_out8(0x03c9, rgb[0] / 4);
        io_out8(0x03c9, rgb[1] / 4);
        io_out8(0x03c9, rgb[2] / 4);
        rgb += 3;
    }
    io_store_eflags(eflags);    /* 恢复flag寄存器 */
    return;
}



//根据像素坐标(x,y)对应的VRAM地址的换算公式写的函数
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
{
    int x, y;
    for (y = y0; y <= y1; y++) {
        for (x = x0; x <= x1; x++)
            vram[y * xsize + x] = c;
    }
    return;
}

那段汇编不解释了。 其中什么_io_in16,_io_in32作者说留到以后解释,那就留到以后吧。

原文地址:https://www.cnblogs.com/You0/p/4432438.html