x86内核解压引导程序开发与地址重定位 - 第1节

1.1 x86 内核启动流程概述

x86 体系结构从加电复位到内核入口点经历多个阶段,每个阶段都涉及模式切换、地址空间重组与数据搬运。理解整条链路是后续解压缩与重定位分析的基础。

1.1.1 启动阶段全景

核心认知:x86 启动不是“一条直线”,而是“多次跳转 + 多次模式切换”的接力过程。BIOS → Bootloader → 内核入口之间,地址映射、CPU 模式、数据压缩状态都在变化。
x86 内核启动流程全景图 BIOS 实模式 16-bit Bootloader 实模式 → 保护模式 解压缩阶段 保护模式 32-bit 地址重定位 分页模式 各阶段关键特征 • BIOS:固件自检 → 加载 MBR/GPT → 跳转至 Bootloader 入口(0x7C00) • Bootloader:GRUB/Syslinux → 读取内核映像 → 从实模式切换到保护模式 • 解压缩:内核映像通常为 gzip/LZMA 压缩 → 解压到临时缓冲区 • 重定位:修正符号地址 → 建立页表 → 跳转到解压后的内核入口 • 最终:进入 start_kernel() → 初始化子系统 → 挂载根文件系统

1.1.2 启动阶段对比表

1.2 解压缩与重定位的重要性

1.2.1 为什么需要解压缩?

  • 存储空间约束:早期 x86 内核映像存储在软盘/硬盘的有限扇区中,压缩可减小映像体积 2~4 倍。
  • 加载速度平衡:I/O 读取压缩映像的时间 + 解压时间 < 直接读取未压缩映像的时间。
  • 嵌入式场景:Flash/ROM 容量有限,压缩内核是标配。
工程事实:Linux 内核的 arch/x86/boot/compressed/ 目录专门存放解压缩 stub 代码,该 stub 在保护模式下执行,负责将内核主体从 .gz 或 .xz 格式解压到物理内存高位区域。

1.2.2 为什么需要地址重定位?

内核在编译链接时假设一个“链接地址”(Link Address),但实际加载到物理内存时可能不在该地址。重定位修正所有绝对地址引用,使代码能在任意基地址正确执行。

地址重定位核心问题 链接地址 0xC0100000 加载地址 0x00100000 重定位后 修正偏移 +0x100000 关键公式:重定位偏移 = 加载地址 − 链接地址 所有绝对跳转、数据访问、中断向量表地址都需要加上该偏移量。

1.2.3 不解压缩/不重定位的后果

阶段CPU 模式地址宽度代码来源典型入口
BIOS实模式20-bit主板 ROM0xFFFF0
Bootloader 第一阶段实模式20-bitMBR/VBR0x7C00
Bootloader 第二阶段保护模式32-bit文件系统GRUB core
解压缩 stub保护模式32-bit内核映像头部startup_32
内核入口分页模式32/64-bit解压后内存start_kernel

1.3 课程目标与前置知识

1.3.1 课程目标

  • 掌握 x86 实模式 → 保护模式 → 分页模式的切换汇编实现。
  • 理解 gzip/LZMA 解压缩算法在 x86 环境下的适配原理。
  • 实现完整的地址重定位流程:从 ELF 解析到符号修正。
  • 构建一个可运行的最小内核解压缩 + 重定位工程案例。
  • 熟练使用 GDB + QEMU 调试启动阶段的汇编代码。

1.3.2 前置知识清单

场景后果典型现象
跳过解压缩CPU 执行压缩数据流,指令乱码#UD 异常 / 三重故障
链接地址 ≠ 加载地址绝对跳转指向错误地址Page Fault / 死循环
数据段未重定位全局变量访问越界内核 panic / 数据损坏
栈指针未修正栈操作破坏内核代码不可恢复崩溃
⚠ 重要提示:本课程不从头教授 x86 汇编基础。如果你对 lgdt、mov cr0, eax、jmp far ptr 等指令不熟悉,请先完成前置学习。课程中所有汇编代码均使用 AT&T 语法(GAS),与 Intel 语法有差异,请提前适应。

1.3.3 课程工程环境

  • 主机:Linux (Ubuntu 22.04+ / Debian 12+)
  • 交叉编译器:i386-elf-gcc (或 x86_64-linux-gnu-gcc -m32)
  • 模拟器:QEMU 7.0+ (qemu-system-i386)
  • 调试器:GDB 12+ (支持 target remote)
  • 构建工具:GNU Make 4.0+
课程定位:这不是理论课,而是“手写汇编 + 调试 + 排错”的工程实战。每章都包含可编译、可运行、可调试的代码案例。你将在 QEMU 中亲眼看到解压缩前后的内存变化,以及重定位如何修正符号地址。
领域具体要求推荐资源
x86 汇编熟悉 MOV/JMP/CALL/LODSB/STOSB 等基本指令;理解段寄存器、EFLAGS《x86 汇编语言:从实模式到保护模式》
C 语言指针运算、结构体、内联汇编(asm volatile)《C 程序设计语言》K&R
计算机体系结构内存层次、MMU、TLB、缓存一致性基础《深入理解计算机系统》CS:APP
ELF 文件格式节头表、程序头表、重定位表结构ELF 规范 / man 5 elf
工具链GCC 交叉编译、LD 链接脚本、Makefile、QEMU、GDBGNU 工具链文档