理论讲解: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. 将第1-24行的内容复制到第0-23行
  2. 清空第24行(最后一行)
  3. 更新光标位置

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, ...);        // 格式化输出