了解 x86
汇编语言 和 PC 开机引导(bootstrap)过程
QWMU x86 模拟器 started with QEMU and QEMU/GDB debugging
1. Getting Started with x86 assembly
汇编语言手册:The PC Assembly Language Book
We do recommend reading the section "The Syntax" in Brennan's Guide to Inline Assembly.
when reading and writing x86 assembly: the 6.828 reference page
80386 Programmer's Reference Manual
IA-32 Intel Architecture Software Developer's Manuals
2. Simulating the x86
使用模拟器,代码可以在物理PC运行,支持断点debug等
In 6.828 we will use the QEMU Emulator, a modern and relatively fast emulator,which can act as a remote debugging target for the GNU debugger (GDB),
Ububtu
需要安装 32位gcc
multilib
: gcc-multilib package
Now you're ready to run QEMU, supplying the file obj/kern/kernel.img
, created above, as the contents of the emulated PC's "virtual hard disk." This hard disk image contains both our boot loader (obj/boot/boot
) and our kernel (obj/kernel
).
启动模拟器: make qemu-nox
***
*** Use Ctrl-a x to exit qemu
***
qemu-system-i386 -nographic -drive file=obj/kern/kernel.img,index=0,media=disk,format=raw -serial mon:stdio -gdb tcp::26000 -D qemu.log
6828 decimal is XXX octal!
entering test_backtrace 5
entering test_backtrace 4
entering test_backtrace 3
entering test_backtrace 2
entering test_backtrace 1
entering test_backtrace 0
leaving test_backtrace 0
leaving test_backtrace 1
leaving test_backtrace 2
leaving test_backtrace 3
leaving test_backtrace 4
leaving test_backtrace 5
Welcome to the JOS kernel monitor!
Type 'help' for a list of commands.
K>
Kernel Info:
K> kerninfo
Special kernel symbols:
_start 0010000c (phys)
entry f010000c (virt) 0010000c (phys)
etext f01019e9 (virt) 001019e9 (phys)
edata f0113060 (virt) 00113060 (phys)
end f01136a0 (virt) 001136a0 (phys)
Kernel executable memory footprint: 78KB
K>
3. PC 的物理地址空间
+------------------+ <- 0xFFFFFFFF (4GB)
| 32-bit |
| memory mapped |
| devices |
| |
/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\
| |
| Unused |
| |
+------------------+ <- depends on amount of RAM
| | 为了兼容早期 1MB 的机型,这部分被划分为 Extended Memory
| |
| Extended Memory |
| |
| |
+------------------+ <- 0x00100000 (1MB)
| BIOS ROM | <- 64KB
+------------------+ <- 0x000F0000 (960KB)
| 16-bit devices, |
| expansion ROMs |
+------------------+ <- 0x000C0000 (768KB)
| VGA Display |
+------------------+ <- 0x000A0000 (640KB)
| |
| Low Memory |
| |
+------------------+ <- 0x00000000
现在的x86处理器可以支持4GB以上的物理RAM,因此RAM可以进一步扩展到0xFFFFFFFF以上。在这种情况下,BIOS必须安排在32位可寻址区域顶部的系统RAM中留下第二个孔,为这些32位设备留出空间。由于设计限制,无论如何,JOS将只使用PC的物理内存的第一个256MB,所以现在我们将假装所有PC“仅”拥有32位物理地址空间。但是处理复杂的物理地址空间和多年来发展的硬件组织的其他方面是OS开发的重要实际挑战之一。
4. The ROM BIOS (Basic Input/Output System)
使用QEMU的调试工具来研究IA-32兼容计算机的启动方式
打开两个终端:
enter make qemu-gdb
(or make qemu-nox-gdb
).
这将启动QEMU,但QEMU在处理器执行第一条指令之前停止,并等待来自GDB的调试连接。
在另一个终端 run make gdb
|
|
其中第一行为GDB反汇编出的第一条要执行的指令,从中可以发现:
- 这台 IBM PC 从物理地址
0x0000_fff0
开始执行,由上图可知,它位于为ROM BIOS保留的64KB区域的最顶端。 - PC 从
CS = 0xf000
和IP = 0xfff0
开始执行 - 第一条执行的指令是
jmp
, 他会跳转到分段地址 (segment address)CS = 0xf000
andIP = 0xe05b
.
之所以这样模拟是因为Intel 8088处理器的BIOS位置绑定在了0x0000fff0
, 保证了启动时首先由 BIOS 接管机器,而此时没有其他软件可以运行,因此需要跳转到指定地址
最终的跳转地址为:(CS:IP) => (0xf000:fff0) 映射的物理内存地址
这里应用了 实模式寻址(real mode addressing)
$\text{physical address} = 16 \times segment + offset $
即: (*16就是补0,segment可以参考cache block理解)
|
|
!> 练习二:使用gdb命令 si
(Step instruction)追踪BIOS,需要结合 x86 汇编手册,暂时不看。

启动顺序:
After initializing the PCI bus and all the important devices the BIOS knows about, it searches for a bootable device such as a floppy, hard drive, or CD-ROM. Eventually, when it finds a bootable disk, the BIOS reads the boot loader from the disk and transfers control to it.