bochs 中文文档 下载 App

寄存器查看与修改——通用寄存器、段寄存器、EFLAGS 和 CR 系列

info registers:一次性看全部

bochs:1> info registers

输出示例:

CPU0:
rax=0000000000000000 rbx=0000000000000000 rcx=0000000000000000
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rbp=0000000000000000 rsp=0000000000000000
 r8=0000000000000000  r9=0000000000000000 r10=0000000000000000
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
rip=0000000000007c00
eflags=00000002
 iopl=0         nv up ei pl nz na po nc
cs=0000  ds=0000  es=0000  ss=0000  fs=0000  gs=0000
gdt=0000000000000000  gdtr=0000000000000000
idt=0000000000000000  idtr=0000000000000000
ldt=0000000000000000  ldtr=0000000000000000
tr =0000000000000000
dr0=0000000000000000 dr1=0000000000000000
dr2=0000000000000000 dr3=0000000000000000
dr6=0000000000000000 dr7=0000000000000000
cr0=00000010 cr2=00000000 cr3=00000000
cr4=00000000

寄存器分几类

类别寄存器OS 开发关注点
通用RAX-R15函数参数、返回值、临时变量
指令指针RIP当前执行位置
栈指针RSP / RBP栈帧结构
段寄存器CS/DS/ES/SS/FS/GS段基址、段限、权限(保护模式)
控制寄存器CR0-CR4分页开关、保护模式开关、PAE
调试寄存器DR0-DR7硬件断点(内核调试用)
表寄存器GDTR/IDTR/LDTR/TR段描述符表、中断描述符表
标志EFLAGS进位/零/溢出/中断开关

OS 开发最关注的几个寄存器

EIP / RIP:当前正在执行的指令位置。断点、单步都围绕它。

CR0:最重要的控制寄存器。位含义:

CR0 位名称作用
PE (bit 0)Protection Enable0 = 实模式,1 = 保护模式
MP (bit 1)Monitor CoprocessorFPU 存在标志
EM (bit 2)Emulate1 = 模拟 FPU(OS 自己处理)
TS (bit 3)Task Switched每次任务切换置位,触发 FPU 异常
ET (bit 4)Extension Type80387/80287
NE (bit 5)Numeric Error1 = 用内部 FPU 错误处理
WP (bit 16)Write Protect1 = 内核写只读页也触发异常
PG (bit 31)Paging0 = 不分页,1 = 开启分页

内核初始化流程就是逐步打开 CR0 的 PE → PG 等位。调试器里观察 CR0 变化能验证你的模式切换代码有没有问题。

CR3:页表根。内核每次切换页表(进程切换)都会改 CR3。调试"进程切换时页表没换对"这类问题,在 CR3 上设 watchpoint 就能抓到。

EFLAGS:16 个标志位,OS 开发常看:

位名称含义
CF (0)Carry Flag无符号进位
PF (2)Parity Flag奇偶校验
ZF (6)Zero Flag结果为 0
SF (7)Sign Flag结果为负
IF (9)Interrupt Flag1 = 开中断
TF (8)Trap Flag1 = 单步陷阱(调试用)

段寄存器(保护模式下):实模式下段寄存器就是基址左移 4 位。保护模式下段寄存器是选择子(selector)——指向 GDT 或 LDT 里的段描述符。调试器的 info sreg 可以同时显示选择子、段基址、段限、DPL:

bochs:1> info sreg
cs=0010 ds=0018 es=0018 ss=0018 fs=0000 gs=0000
CS: 0x0010: 32bit data segment, base=0x00000000, limit=0x000fffff
             DPL=0, accessed=0, writable=0, expand_down=0
DS: 0x0018: 32bit data segment, base=0x00000000, limit=0xffffffff
             DPL=0, accessed=0, writable=1, expand_down=0

修改寄存器

语法:set $<name> = <value>

bochs:1> set $eax = 0x42         # 设置 EAX
bochs:2> set $eip = 0x7c00       # 把执行指针跳回 0x7c00(比如想重新执行 Bootloader)
bochs:3> set $cr0 = 0x00000010   # 关掉分页(PG 位清零)
bochs:4> set $if = 1             # 打开中断(EFLAGS 的 IF 位置 1)

set $eip = value 特别有用——可以让模拟"回到过去"重新跑一段代码,省了重启 Bochs 的时间。

修改 EFLAGS 标志位

bochs:1> set $zf = 1             # 设置 Zero Flag
bochs:2> set $cf = 0             # 清除 Carry Flag
bochs:3> set $if = 0             # 关中断

32 位 vs 64 位寄存器

32 位模式下 Bochs 调试器显示 EAX/EBX/... 等 32 位寄存器名。64 位模式下显示 RAX/RBX/... 等完整 64 位寄存器名。

info registers 会自动根据当前 CPU 模式调整输出格式。不用手动切换。

如果想强制看 32 位视图(即使 64 位模式),可以用 info registers eflags 或 info registers cr0 等过滤器只看特定寄存器。

info msr:Model-Specific Registers

某些 CPU 特性(SYSCALL/SYSRET、FS/GS 基址、TSC)通过 MSR 控制。调试器可以列出:

bochs:1> info msr

输出会列出所有当前有值的 MSR(通常只显示内核写过的那些)。对于调试 x86-64 内核的 SYSCALL 路径或 FS/GS 设置,info msr 是关键工具。

info port:I/O 端口查看

bochs:1> info port 0x3f8        # COM1 串口基址
bochs:2> info port 0xcf8        # PCI 地址端口
bochs:3> info port 0x220        # SB16 默认基址

某些 OS 内核(特别是早期版本)通过 I/O 端口和硬件通信——调试端口读写时这个命令很有用。

小结:OS 开发的寄存器速查表

需求命令
看当前指令位置info registers eip
看页表根(CR3)info cr
切换保护模式 / 分页info cr 看 CR0
看是否开中断info flags 看 IF
看 CS/DS/SS 段基址info sreg
强制重置 PCset $eip = 0x7c00
关中断set $if = 0