QEMU中汇编OS代码设置文本红色无效的解决方法
引导加载器文本颜色设置问题解决
问题说明
尝试在16位BIOS引导加载器中,通过在字符串里插入0x04(对应红色)作为颜色控制字符,实现部分文本红色显示,但运行qemu-system-x86_64 -fda C:\Users\Ukraine\Documents\CyberOS\boot.bin后颜色未生效。
原始核心代码片段:
hello db 'CyberOS terminal edition', 0x04, 'version 0.1a', 0x0A, 'created by SomeOne_GuY', 0 ;вивести на екран print_string: mov ah, 0x0E ;Значення яке оброблює переривання, щоб зробити значення з усіх та вивести на екран .repeat_next_char: lodsb ;завантажуємо перший символ з того hello: символ "C" cmp al, 0 je .done_print int 0x10 ;переривання відео виклику BIOS jmp .repeat_next_char
问题原因
BIOS的INT 0x10 AH=0x0E(电传打字机输出模式)仅负责输出ASCII字符,不会自动解析颜色控制码。要改变文本颜色,必须通过修改寄存器BL(文本属性)来实现:
BL低4位:前景色(0=黑,4=红,7=白等)BL高4位:背景色(0=黑,4=红等)
解决方案
方案1:在打印函数中识别控制码切换颜色
修改print_string函数,让它检测到颜色控制字符时,更新BL寄存器的属性值:
[bits 16] [org 0x7c00] start: xor ax, ax mov ds, ax mov es, ax ; 初始化彩色文本模式(确保颜色属性生效) mov ah, 0x00 mov al, 0x03 ; 80x25彩色文本模式 int 0x10 mov si, hello call print_string jmp $ ; 无限循环,避免执行后续数据 hello db 'CyberOS terminal edition', 0x04, 'version 0.1a', 0x0A, 'created by SomeOne_GuY', 0 print_string: mov ah, 0x0E mov bh, 0x00 ; 视频页号固定为0 mov bl, 0x07 ; 默认属性:白字黑底 .repeat_next_char: lodsb cmp al, 0 je .done_print ; 检测颜色控制码0x04,切换为红字黑底 cmp al, 0x04 je .set_red_color ; 输出当前字符 int 0x10 jmp .repeat_next_char .set_red_color: mov bl, 0x04 ; 设置前景色为红色 jmp .repeat_next_char .done_print: ret times (510 -($-$$)) db 0x00 dw 0xAA55
方案2:拆分字符串分别设置颜色
把不同颜色的文本拆分为独立字符串,调用带颜色参数的打印函数:
[bits 16] [org 0x7c00] start: xor ax, ax mov ds, ax mov es, ax mov ah, 0x00 mov al, 0x03 int 0x10 ; 输出第一部分(默认白字) mov si, hello_part1 mov bl, 0x07 call print_string_with_color ; 输出第二部分(红字) mov si, hello_part2 mov bl, 0x04 call print_string_with_color ; 输出第三部分(默认白字) mov si, hello_part3 mov bl, 0x07 call print_string_with_color jmp $ hello_part1 db 'CyberOS terminal edition', 0 hello_part2 db 'version 0.1a', 0x0A, 0 hello_part3 db 'created by SomeOne_GuY', 0 print_string_with_color: mov ah, 0x0E mov bh, 0x00 .repeat_next_char: lodsb cmp al, 0 je .done_print int 0x10 jmp .repeat_next_char .done_print: ret times (510 -($-$$)) db 0x00 dw 0xAA55
关键注意点
- 必须先初始化视频模式为
0x03(彩色文本模式),否则颜色属性可能不生效 - 添加
jmp $无限循环,防止CPU执行到字符串变量的字节(把数据当指令执行会导致错误) BL的属性值可以自由组合,比如0x47是白字红底,0x0C是亮红字黑底
内容的提问来源于stack exchange,提问作者Dmytro Parkhomenko
相关产品推荐
相关产品推荐

