华纳云:当我们按下开机键后,发生了什么?
字数 1215 2025-08-15 21:34:08
计算机启动过程详解
前置知识
理解计算机启动过程需要掌握以下基本概念:
- 内存功能:内存是存储数据的地方,给出地址信号可返回对应数据
- CPU工作原理:CPU不断从内存中取出指令并执行
- 程序计数器(PC):决定CPU从内存哪个地址取指令,会不断+1或由跳转指令修改
启动过程核心机制
1. BIOS主导启动的原因
计算机启动时,CPU的PC寄存器被强制初始化为0xFFFF0,这是BIOS程序的入口地址。具体实现方式:
- 段基址寄存器cs初始化为
0xF000 - 偏移地址寄存器IP初始化为
0xFFF0 - 实模式下最终地址计算:
cs左移4位 + IP = 0xFFFF0
2. 内存映射机制
CPU地址总线宽度决定可访问内存空间大小,但并非全部分配给内存:
- 部分地址空间分配给外设(显存、硬盘控制器等)
- 外设存储区域被"映射"到内存特定区域
- 实模式下(开机时)只有1MB内存可用
3. 实模式内存分布
BIOS空间被映射到内存0xC0000-0xFFFFF,其中:
- 系统BIOS位于
0xF0000-0xFFFFF - BIOS程序占用内存开头区域(如中断向量表)
BIOS执行流程
-
初始跳转:
0xFFFF0处指令:jmp far f000:e05b- 跳转到
0xFE05B执行BIOS核心代码
-
BIOS主要工作:
- 硬件检测和初始化
- 建立中断向量表并填写中断例程
- 最后加载启动区
启动区加载机制
1. 启动区识别
BIOS按启动顺序检查设备:
- 读取每个设备的
0盘0道1扇区(512字节) - 检查最后两个字节是否为
0x55和0xAA - 找到符合条件的第一个设备作为启动设备
2. 启动区加载
- 将512字节启动区内容复制到内存
0x7C00 - 执行跳转指令使PC指向
0x7C00 - 控制权转交给启动区代码
3. 0x7C00的由来
历史原因:
- 第一个BIOS(IBM PC 5150)假设操作系统最小需要32KB内存
- 为安全预留空间:32KB末尾(
0x8000)减去1KB(0x400) =0x7C00 - 后续保持兼容性无法更改
启动区代码功能
启动区主要任务:
- 加载真正的操作系统内核到内存
- 跳转到内核入口地址
典型启动区代码结构示例:
; hello-os
ORG 0x7c00 ; 声明加载地址
entry:
; 初始化寄存器
MOV AX,0
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX
MOV ES,AX
; 显示消息
MOV SI,msg
putloop:
MOV AL,[SI]
ADD SI,1
CMP AL,0
JE fin
MOV AH,0x0e
MOV BX,15
INT 0x10
JMP putloop
fin:
HLT
JMP fin
msg:
DB 0x0a,0x0a ; 换行
DB "hello-os"
DB 0x0a ; 换行
DB 0 ; 结束符
RESB 0x7dfe-$ ; 填充到510字节
DB 0x55, 0xaa ; 启动标识
操作系统内核加载
启动区完成后:
- 从磁盘特定位置加载操作系统内核到内存
- 跳转到内核入口地址
- 内核开始执行:初始化内存管理、进程管理、文件系统等
完整启动流程总结
- 按下电源,CPU PC初始化为
0xFFFF0(一跳) - 跳转到BIOS核心代码
0xFE05B(二跳) - BIOS加载启动区到
0x7C00并跳转(三跳) - 启动区加载操作系统内核并跳转(四跳)
- 操作系统内核开始执行,完成系统初始化
深入学习的建议
要完全理解计算机启动过程,建议:
- 研究实模式和保护模式的内存管理
- 学习x86汇编语言
- 阅读Linux内核源码中启动相关部分
- 实践编写简单的启动区代码