理论讲解:VGA文本模式
1. VGA文本模式基础
显存地址
VGA文本模式的显存映射到物理地址 0xB8000。
屏幕规格
- 列数: 80
- 行数: 25
- 总字符数: 80 × 25 = 2000
- 总字节数: 2000 × 2 = 4000字节
字符编码
每个字符占2字节:
字节0: ASCII字符
字节1: 属性(颜色)
属性字节:
位 7 : 闪烁(通常禁用)
位 6-4 : 背景颜色(0-7)
位 3-0 : 前景颜色(0-15)
颜色表
| 值 | 颜色 | 值 | 颜色 |
|---|---|---|---|
| 0 | 黑色 | 8 | 深灰 |
| 1 | 蓝色 | 9 | 浅蓝 |
| 2 | 绿色 | 10 | 浅绿 |
| 3 | 青色 | 11 | 浅青 |
| 4 | 红色 | 12 | 浅红 |
| 5 | 品红 | 13 | 浅品红 |
| 6 | 棕色 | 14 | 黄色 |
| 7 | 浅灰 | 15 | 白色 |
计算显存偏移
// 第 row 行、第 col 列的字符在显存中的偏移:
int offset = (row * 80 + col) * 2;
// 或使用 uint16_t 指针时:
uint16_t *vga = (uint16_t*)0xB8000;
vga[row * 80 + col] = (color << 8) | character;2. 硬件光标
VGA控制器有一个硬件光标(屏幕上闪烁的下划线)。需要通过I/O端口控制:
端口 0x3D4: VGA控制寄存器索引
端口 0x3D5: VGA控制寄存器数据
寄存器 14 (0x0E): 光标位置高8位
寄存器 15 (0x0F): 光标位置低8位
设置光标位置:
void set_cursor(int offset) {
outb(0x3D4, 14);
outb(0x3D5, (uint8_t)(offset >> 8));
outb(0x3D4, 15);
outb(0x3D5, (uint8_t)(offset & 0xFF));
}3. 滚屏
当输出超过25行时,需要滚屏:
- 将第1-24行的内容复制到第0-23行
- 清空第24行(最后一行)
- 更新光标位置
4. 需要实现的函数
void screen_init(void); // 初始化
void screen_clear(void); // 清屏
void screen_putchar(char c); // 输出单个字符
void screen_puts(const char *str); // 输出字符串
void screen_set_color(uint8_t fg, uint8_t bg); // 设置颜色
void screen_printf(const char *fmt, ...); // 格式化输出