Char * 始终为空终止符

问题描述 投票:0回答:1

我正在尝试实现 VGA 打印功能,但无法将数据视为非空字符。即使我在这个函数内硬编码数据,它仍然会跳过

while
循环。我有一个调试打印,如果计数为零,它会打印
Z
并且它总是打印它并且光标不会移动,所以我非常有信心它不会进入
while
循环

void vga_print(char *data, char mode) {

    char *vga = (char *)(VGA_MEM_LOC);

    uint8_t count = 0;
    while (*data != '\0') {
        if (*data == '\n') {
            current_x = 0;
            current_y++;
        } else {
            *vga++ = *data++;
            *vga++ = mode;
            current_x++;
            if (current_x >= screen_x) {
                current_x = 0;
                current_y++;
            }
        }
        count++;
    }

    // move the cursor
    uint16_t location = current_x + ((current_y) * screen_x);

    x86_port_out(VGA_CRT_INDEX, VGA_CURSOR_LOW);
    x86_port_out(VGA_CRT_DATA,  location);

    x86_port_out(VGA_CRT_INDEX, VGA_CURSOR_HIGH);
    x86_port_out(VGA_CRT_DATA,  location >> 8);
}
c kernel vga
1个回答
0
投票

函数存在问题,但无法解释观察到的行为。全局变量

current_x
current_y
screen_x
或地址
VGA_MEM_LOC
的初始值可能有问题。

这里有一些问题:

  • 所有输出都从 VGA 屏幕缓冲区的基地址开始。
  • current_x
    current_y
    会针对每个字节和换行符进行更新,但
    vga
    指针不会移动,因此下一个字符会粘在前一个输出上。
  • data
    时不要增加
    *data == '\n'
    :这会导致无限循环。
  • 您不处理
    current_y >= screen_y
    的情况。

这是修改后的版本:

void vga_print(const char *data, unsigned char mode) {

    uint16_t *vga = (uint16_t *)(VGA_MEM_LOC);
    uint16_t location = current_x + current_y * screen_x;
    uint8_t ch;

    while ((ch = *data++) != '\0') {
        if (ch == '\n' || current_x >= screen_x) {
            current_x = 0;
            current_y++;
            location = current_y * screen_x;
            if (current_y >= screen_y) {
                current_y = screen_y - 1;
                location = current_y * screen_x;
                // shift the screen contents up one line
                memmove(vga, vga + screen_x, sizeof(*vga) * location);
                // erase the bottom line
                for (int i = 0; i < screen_x; i++) {
                    vga[location + i] = ' ' | (mode << 8);
                }
            }
            if (ch != '\n') {
                vga[location++] = ch | (mode << 8);
                current_x++;
            }
        }
    }

    // move the cursor

    x86_port_out(VGA_CRT_INDEX, VGA_CURSOR_LOW);
    x86_port_out(VGA_CRT_DATA,  location);

    x86_port_out(VGA_CRT_INDEX, VGA_CURSOR_HIGH);
    x86_port_out(VGA_CRT_DATA,  location >> 8);
}
© www.soinside.com 2019 - 2024. All rights reserved.