VGA打印函数无法进入while循环:char*始终为空终止符
VGA打印函数无法进入while循环的问题解决
问题描述
我正在实现一个VGA打印函数,但传入的data始终被识别为空字符,即便在函数内硬编码数据,程序也会跳过while循环。调试时发现每次count都是0(触发打印Z的逻辑),光标也未移动,确认程序完全没进入循环。
代码实现如下:
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++; } // 移动光标 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); }
补充信息:将字符串初始化为char example[] = "xyz\0"而非char *example = "xyz\0"时,函数即可正常工作。
问题原因
核心差异在于字符串的存储位置与内存访问权限:
- 使用
char *example = "xyz\0"时,"xyz\0"属于字符串字面量,编译器默认会将其放入只读数据段(.rodata)。在内核开发场景中,如果页表未正确映射该只读段,或者当前运行模式(如早期保护模式/实模式)无法访问这段内存,读取*data时会得到错误值(通常是0),直接导致循环条件不成立。 - 使用
char example[] = "xyz\0"时,字符串字面量会被复制到栈或全局数据段的数组中,这段内存处于可正常访问的区域,因此函数能正确读取到字符串内容。
解决方案
- 优先使用数组存储字符串:对于需要打印的字符串,直接用
char str[] = "目标内容"的方式定义,确保数据位于可访问的内存区域。 - 修复只读段的内存映射:若必须使用字符串字面量,需在内核页表配置中,将
.rodata段映射为可读内存,保证CPU能正常读取其中的数据。 - 校验指针有效性:调用
vga_print前,确认传入的data指针指向的内存已正确初始化且具备访问权限,避免传入未映射或权限错误的地址。
额外代码修复
原代码存在一个潜在bug:当遇到'\n'时,未移动data指针,若后续能进入循环,会导致死循环。需在换行分支中添加指针移动逻辑:
if (*data == '\n') { current_x = 0; current_y++; data++; // 新增该行,避免死循环 }
内容的提问来源于stack exchange,提问作者octalgon
相关产品推荐
相关产品推荐

