我正在尝试实现 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);
}
函数存在问题,但无法解释观察到的行为。全局变量
current_x
、current_y
、screen_x
或地址VGA_MEM_LOC
的初始值可能有问题。
这里有一些问题:
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);
}