内置调试器概览——bochsdbg 启动、调试器命令集合和编译开关
bochsdbg vs bochs
Windows 官方二进制包里自带两个可执行文件:
| 文件 | 调试器 | 行为 |
|---|---|---|
bochs.exe | ❌ 不带 | 启动后直接执行模拟(不停) |
bochsdbg.exe | ✅ 带 | 启动后停在 bochs:1> 调试器提示,等待命令 |
Linux / macOS 上没有这个区分——一个 bochs 二进制同时包含两种模式。用 bochsrc 里的 debug: 关键字或命令行 -q 参数控制启动行为:
bochs -q:跳过 Launcher,直接开始执行(如果编译时带了调试器,会在第一条指令前停住)bochsdbg(某些发行版改名):进入调试器模式
核心点:调试器能力在编译时决定。编译时加 --enable-debugger + --enable-disasm,二进制就有调试器。没加的话,Windows 上你就找不到 bochsdbg.exe,Linux/macOS 上 bochs 也只会直接执行。
调试器启动时发生了什么
bochsdbg 启动后:
========================================================================
Bochs x86 Emulator 3.1
from source on Dec 14 2026
...
========================================================================
0000000000000000i[CPU0 ] CPU is in real mode (active)
0000000000000000i[CPU0 ] CS.mode = 16 bit
0000000000000000i[CPU0 ] SS.mode = 16 bit
0000000000000000i[CPU0 ] EFER = 0x00000000
0000000000000000i[CPU0 ] CR0 = 0x00000010
bochs:1>
bochsrc 里的 log: 关键字指定日志文件路径,如果 panic 事件设了 action=ask,Bochs 在遇到严重错误时也会自动进入调试器。
调试器命令总览
Bochs 调试器的命令体系大致可以分为几类:
控制类
| 命令 | 说明 |
|---|---|
c | continue — 继续执行 |
s(或 step) | 单步执行一条指令 |
n(或 next) | 单步跳过(跳过 CALL) |
fin | step out(跳出当前函数) |
q | 退出 Bochs |
Ctrl-C | 随时中断执行回到调试器 |
断点类
| 命令 | 说明 |
|---|---|
b <addr> | 设置地址断点(或 pb 物理断点、vb 虚拟断点) |
info break | 列出所有断点 |
d <num> | 删除断点 |
lb | 删除所有断点 |
sb <addr> | 设置单条指令断点(执行一次自动删除) |
寄存器类
| 命令 | 说明 |
|---|---|
info registers | 显示所有寄存器 |
info flags | 显示 EFLAGS 标志位 |
set $rax = value | 修改寄存器 |
info cr | 显示 CR0-CR4 |
info msr | 显示 MSR(Model-Specific Registers) |
info sreg | 显示段寄存器(CS/DS/ES/SS/FS/GS + TR/LDTR/GDTR/IDTR) |
内存类
| 命令 | 说明 |
|---|---|
xp <addr> | 查看物理内存(Physical) |
x <addr> | 查看虚拟内存(由 CR3 翻译) |
wx <addr> <value> | 写物理内存 |
w <addr> <value> | 写虚拟内存 |
info pci | PCI 设备枚举结果 |
info port <port> | 查看 I/O 端口 |
反汇编类(需要 --enable-disasm)
| 命令 | 说明 |
|---|---|
u(或 disassemble) | 反汇编当前 EIP 指向的指令 |
u <addr> | 反汇编指定地址 |
u <addr> <count> | 反汇编 count 条指令 |
辅助类
| 命令 | 说明 |
|---|---|
help | 查看所有可用命令 |
help <command> | 查看某命令的详细用法 |
show feature | 显示编译时启用的特性 |
trace | 打开指令追踪(每条指令执行后打印) |
undisasm on | 开启反汇编模式(每条指令都反汇编后执行) |
内存查看的格式后缀
x / xp 命令可以带格式后缀控制显示方式:
xp /16bx 0x7c00 # 16 字节十六进制(bx = byte hex)
xp /4wx 0x7c00 # 4 字十六进制(wx = word hex,2 字节)
xp /2lx 0x7c00 # 2 双字十六进制(lx = long hex,4 字节)
xp /1s 0x7c00 # 字符串(以 null 结尾)
和 GDB 的对比
Bochs 调试器和 GDB 有类似的命令体系(b 断点、c 继续、s 单步、info registers 寄存器),但核心区别:
| 维度 | Bochs 调试器 | GDB |
|---|---|---|
| 视角 | 硬件级(模拟的 CPU/内存/设备状态) | 软件级(进程/线程/源码级) |
| 断点 | 物理/虚拟地址都可以 | 仅虚拟地址 |
| 内存 | 物理 + 虚拟,前缀区分 | 仅虚拟 |
| 反汇编 | 硬件指令级(和源码无关) | 可以和源码对应 |
| 核心场景 | OS 内核开发、驱动调试、逆向 | 应用程序开发 |
| 源码支持 | 无(不关心源码) | 完整(需要编译时 -g) |
| 双机调试 | 不需要 | GDB stub + GDB 客户端 |
Bochs 调试器没有源码级调试能力——它只知道机器码。如果你想调试 C 语言内核,需要自己把机器码地址和源码行号对应起来(通常用 addr2line 或 objdump 来辅助)。
快速上手:三个常用命令组合
OS 开发者最常用的调试器命令三件套:
组合一:定位 Bootloader 入口
bochs:1> b 0x7c00 # 在物理地址 0x7c00 下断点
bochs:2> c # 继续执行
# 调试器停在 Bootloader 第一条指令
bochs:3> u # 反汇编当前指令
bochs:4> info registers # 看 CS/IP 等寄存器
组合二:逐条追踪内核启动
bochs:1> trace # 开启追踪模式
bochs:2> c # 继续
# 每条指令执行后打印反汇编,非常慢但极其精确
# Ctrl-C 随时中断
组合三:检查页表
bochs:1> info cr # 看 CR3 值
bochs:2> xp /16lx <CR3值&0xfffff000> # 看 PML4 表的 16 项
bochs:3> x /16lx <虚拟地址> # 看虚拟地址对应的物理翻译结果
编译验证
在 bochsdbg 里运行 show feature 确认调试器和反汇编器都在:
bochs:1> show feature
feature: debugger, disasm, x86-64
如果只有 debugger 没有 disasm,编译时加 --enable-disasm 重编译。反汇编器对 OS 调试是刚需。