printf的一个BUG是每次打印字符都从固定的位置0xb8000开始,下一次打印将覆盖上一次的内容。

unsigned short *VideoMemory = (unsigned short*)0xb8000;

屏幕的大小是80 x 25,每输出80个字节需要进行换行,每满25行需要清屏,
打印位置重置为第一行行首。
然而屏幕在内存中的地址是连续的,
我们可以给光标增加一个X Y
而因为char为一个字节,所以我们可以直接通过x++来进行光标的移动。
因此可以用VideoMemory[80 * y + x]来访问第y行第x位。如果遇到换行符,则直接进行换行。

void printf(const char *str)
{
    // screen address
    static uint16_t *VideoMemory = (uint16_t*)0xb8000;
    static uint8_t x = 0, y = 0;

    for (int i = 0; str[i]; i++)
    {
        switch (str[i])
        {
            case '\n':
                y++;
                x = 0;
                break;
            default:
                VideoMemory[80 * y + x] = (VideoMemory[80 * y + x] & 0xFF00) | str[i];
                x++;
        }

        if (x >= 80)
        {
            x = 0;
            y++;
        }
        if (y >= 25)
        {
            for (y = 0; y < 25; y++)
            {
                for (x = 0; x < 80; x++)
                    VideoMemory[i] = (VideoMemory[i] & 0xFF00) | ' ';
            }
            x = 0;
            y = 0;
        }
    }
}

标签: none

评论已关闭