CPU和内存基础
1. CPU寄存器
CPU内部有一些高速存储单元,叫做寄存器。操作系统开发中需要了解的主要寄存器:
1.1 通用寄存器
| 64位 | 32位 | 16位 | 用途 |
|---|---|---|---|
| RAX | EAX | AX | 累加器,常用于运算和返回值 |
| RBX | EBX | BX | 基址寄存器 |
| RCX | ECX | CX | 计数器,循环计数 |
| RDX | EDX | DX | 数据寄存器,I/O操作 |
| RSI | ESI | SI | 源地址(字符串操作) |
| RDI | EDI | DI | 目的地址(字符串操作) |
| RBP | EBP | BP | 栈基址指针 |
| RSP | ESP | SP | 栈顶指针 |
📝 64位寄存器以 R 开头,32位以 E 开头,16位直接是两字母。 在实模式(16位)中使用 AX、BX 等,保护模式(32位)使用 EAX、EBX 等。
1.2 段寄存器
| 寄存器 | 名称 | 用途 |
|---|---|---|
| CS | 代码段 | 指向当前执行的代码所在的段 |
| DS | 数据段 | 指向数据存储的段 |
| SS | 栈段 | 指向栈所在的段 |
| ES | 附加段 | 额外的数据段 |
| FS | 附加段 | 通常用于线程本地存储 |
| GS | 附加段 | 通常用于系统数据 |
1.3 特殊寄存器
| 寄存器 | 用途 |
|---|---|
| RIP/EIP/IP | 指令指针 - 指向下一条要执行的指令 |
| RFLAGS/EFLAGS | 标志寄存器 - 存储运算结果的状态 |
| CR0 | 控制寄存器0 - 包含保护模式开关 |
| CR3 | 控制寄存器3 - 页目录基地址 |
1.4 标志寄存器中的关键位
EFLAGS:
CF (Carry Flag) - 进位标志,无符号运算溢出
ZF (Zero Flag) - 零标志,结果为零时置1
SF (Sign Flag) - 符号标志,结果为负时置1
IF (Interrupt Flag) - 中断标志,1=允许中断
DF (Direction Flag) - 方向标志,字符串操作方向
2. 指令执行周期
CPU执行每条指令的过程:
取指(Fetch) → 解码(Decode) → 执行(Execute) → 写回(Write-back)
↑ |
└──────────────────────────────────────────────┘
- 取指: 从内存中读取 RIP 指向的指令
- 解码: 分析指令的操作码和操作数
- 执行: 执行运算或内存访问
- 写回: 将结果写入寄存器或内存
3. CPU模式
x86 CPU有三种主要工作模式:
| 模式 | 位数 | 可寻址空间 | 特点 |
|---|---|---|---|
| 实模式 (Real Mode) | 16位 | 1MB | 开机默认模式,无内存保护 |
| 保护模式 (Protected Mode) | 32位 | 4GB | 有内存保护和特权级 |
| 长模式 (Long Mode) | 64位 | 16EB | 现代操作系统使用 |
启动过程的模式切换:
开机 → 实模式(16位) → 保护模式(32位) → 长模式(64位)
我们的教程将从实模式开始,逐步切换到高级模式。
4. 内存基础
4.1 物理地址 vs 逻辑地址
- 物理地址: 内存芯片上的真实位置
- 逻辑地址: 程序看到的地址(可能经过段或页的转换)
实模式寻址(段:偏移):
物理地址 = 段基址 × 16 + 偏移量
例: CS=0x07C0, IP=0x0000
物理地址 = 0x07C0 × 16 + 0x0000 = 0x7C00
4.2 重要的内存地址
OS开发中你会反复遇到这些地址:
地址范围 用途
─────────────────────────────────────────────
0x00000000 - 0x000003FF 中断向量表(实模式,1KB)
0x00000400 - 0x000004FF BIOS数据区
0x00000500 - 0x00007BFF 可用内存
0x00007C00 - 0x00007DFF 引导扇区(BIOS加载到这里) ← 我们代码的起点
0x00007E00 - 0x0009FFFF 可用内存
0x000A0000 - 0x000BFFFF VGA显存 ← 屏幕输出写这里
0x000C0000 - 0x000FFFFF BIOS ROM
0x00100000 - ... 扩展内存(1MB以上) ← 内核加载到这里
4.3 栈
栈是一种后进先出(LIFO)的数据结构,在内存中向下增长:
高地址
┌──────────┐
│ │ ← 栈底 (EBP)
├──────────┤
│ 局部变量 │
├──────────┤
│ 返回地址 │
├──────────┤
│ 参数 │
├──────────┤
│ │ ← 栈顶 (ESP),向下增长
└──────────┘
低地址
关键操作:
push eax— 将 EAX 压入栈顶(ESP 减小)pop eax— 从栈顶弹出到 EAX(ESP 增大)call func— 压入返回地址,跳转到 funcret— 弹出返回地址,跳转回去