前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何调试操作系统源码

如何调试操作系统源码

作者头像
用户3147702
发布2022-06-27 14:19:27
1.7K0
发布2022-06-27 14:19:27
举报
文章被收录于专栏:小脑斧科技博客

1. 引言

上一篇文章中,我们介绍了如何创建一个简单的引导扇区,触发 BIOS 中断,从而在计算机屏幕上显示出一行我们想要的字符串。 计算机是如何启动的?如何制作自己的操作系统

那么,作为一个程序员,首先想到的问题就是,如何去调试这段汇编代码呢?怎么能够知道程序执行的每一步计算机各个寄存器中的数据是否如我们预期呢? 别急,本节我们就来详细解答。

2. 反汇编

最基本的调试方式就是反汇编,通过将二进制文件反汇编成不带有伪指令的汇编代码,可以看到每一步操作做了什么。 下面的命令将二进制程序反汇编成为 NASM 的汇编源码:

ndisasm -o 0x7c00 boot.bin >> disboot.asm

3. 开源虚拟机 bochs 的调试功能

我们最为希望得到的是一个具备断点调试以及随时查看、关注变量或寄存器的值的功能的调试工具。 开源的虚拟机 bochs 就具备这些强大的调试功能: http://bochs.sourceforge.net/

3.1. bochs 的安装

你可以通过源码编译安装,也可以通过包管理工具进行安装,如果你通过包管理工具安装,需要安装 bochs、bochs-x。 同时,bochs 是一个跨平台的虚拟机,支持 windows、mac 等多个平台,甚至在安卓、IOS 等平台下也可以进行安装,这里不赘述安装过程了,windows、mac 用户可以直接官网下载可执行文件进行安装。 如果你是通过源码编译进行安装,一定要在 configure 执行时添加参数 —enable-debugger 和 —enable-disasm 用以添加调试功能。

3.2. bochs 配置

安装好后,bochs 启动需要至少进行以下配置:

  1. BIOS 映像文件,例如安装包中已经提供的 BIOS-bochs-latest
  2. VGA BIOS 映像文件,例如安装包中已经提供的 VGABIOS-lgpl-latest
  3. 至少一个引导启动磁盘映像文件

下面是我在当前最新的 2.6.11 版本所使用的一个配置:

代码语言:javascript
复制
###############################################################
# Configuration file for Bochs
###############################################################

# how much memory the emulated machine will have
megs: 32

# filename of ROM images
romimage: file=$BXSHARE/BIOS-bochs-latest
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest

# what disk images will be used
floppya: 1_44=c:/Debin/Workspace/code/oranges/boot.img, status=inserted

# choose the boot disk.
boot: floppy

# where do we send log messages?
# log: bochsout.txt

# disable the mouse
mouse: enabled=0

# enable key mapping, using US layout as default.
keyboard: keymap=$BXSHARE/keymaps/x11-pc-us.map

# change mouse capture hotkey
mouse: enabled=1
mouse: type=imps2, enabled=1
mouse: type=serial, enabled=1
mouse: enabled=0, toggle=ctrl+f10

3.3. 启动 bochs

3.3.1. unix 环境

在 linux 或 mac 环境下,执行下面的命令就可以启动 bochs 了:

bochs -f bochsrc

bochsrc 是我们上面编写的配置文件。 执行后,显示出下面的界面:

输入 6,回车,就可以开始调试、运行了。

3.3.2. windows 环境

在 windows 环境下,安装路径中有两个可执行文件:bochs.exe 和 bochsdbg.exe。 顾名思义,bochs.exe 是虚拟机的直接执行文件,而 bochsdbg.exe 则用于对系统的调试。

4. bochs 调试指令

bochs 和我们熟悉的 gdb 界面非常像,可以通过命令进行系统的调试工作。 输入 help 可以看到支持的调试命令。

4.1. 断点

  • vbreak seg:off 或 vb seg:off — 为虚拟地址设置断点
  • lbreak addr 或 lb addr — 为线性地址设置断点
  • pbreak [] addr 或 pb [] addr 或 break [] addr 或 b [] addr — 为物理地址设置断点,[] 表示 是可选的
  • info break — 显示当前断点信息
  • bpd n — 将 n 号断点设置为失效
  • bpe n — 将 n 号断点设置为生效
  • delete n 或 del n 或 d n — 删除 n 号断点

上面的 seg、off、addr 都支持十六进制、十进制或八进制,但支持支下面三种格式:

  1. 十六进制 — 0xcdef0123
  2. 十进制 — 123456789
  3. 八进制 — 01234567

所有的添加断点指令都支持条件触发,条件需要被双引号括起来并放到 if 关键字后,例如:

break 0x123cff if "ax = 0"

4.2. 执行控制

  • c 或 cont 或 continue — 运行到下一断点
  • s [cpu] [count] 或 step [cpu] [count] — 在指定 CPU 上单步执行 count 步,cpu 和 count 都是可选的,默认在当前断点中断的 CPU 上执行,如果 cpu 为 all 则在所有 CPU 上执行,默认执行 1 步
  • q 或 quit 或 exit — 退出执行

4.3. 信息查看

  • r 或 reg 或 regs 或 registers — 列出所有 CPU 整数寄存器列表及存储内容
  • fp 或 fpu — 列出所有 FPU 寄存器及存储内容
  • mmx — 列出所有 MMX 寄存器及存储内容
  • sse 或 xmm — 列出所有 SSE 寄存器及存储内容
  • ymm — 列出所有 AVX 寄存器及存储内容
  • sreg — 显示段寄存器及内容
  • dreg — 显示调试寄存器及内容
  • creg — 显示控制寄存器及内容
  • set reg = expr — 将 CPU 寄存器改为 expr 的值,只支持通用寄存器和指令指针,EFLAGES、段寄存器、浮点指针、SIMD 寄存器不支持修改
  • info cpu — 列出所有 CPU 寄存器及内容
  • info eflags — 显示已解码的 EFLAGS 寄存器
  • info break — 显示所有断点信息
  • info tab — 显示分页地址转换信息
  • info device — 列出支持的设备,在后面加设备参数则显示对应设备状态

4.4. 操作内存

  • x /nuf addr — 查看线性地址 addr 的内存
  • xp /nuf addr — 查看物理地址 addr 的内存
  • setpmem addr datasize val — 将物理地址 addr 中 datasize 大小的值设置到变量 val 中
  • writemem — 内存转储
  • crc addr1 addr2 — 显示物理内存范围 addr1 到 addr2 的 CRC32

4.4.1. 参数取值

上述操作中,参数 /nuf 是可选的,其中 n 表示显示多少个单位,默认为 1,u 表示单位大小,默认为字节,f 表示打印格式,默认为16进制方式打印。

4.4.2. 单位大小取值

u 可以取值:

  • b — 字节单位
  • h — 半字单位(2 字节)
  • w — 字单位(4 字节)
  • g — 巨字单位(8 字节)

4.4.3. 打印方式取值

f 可以取值:

  • x — 16 进制
  • d — 十进制
  • u — 无符号十进制
  • o — 八进制
  • t — 二进制

4.5. 内存监控

  • watch read addr 或 watch r addr — 在物理地址 addr 处加一个读监视点
  • watch write addr 或 watch w addr — 在物理地址 addr 处加一个写监视点
  • watch — 在当前内存位置加一个监视点
  • watch stop — 当遇到监视点时停止模拟(默认动作)
  • watch continue — 当遇到监视点时不停止模拟
  • unwatch addr — 取消监视点
  • unwatch — 取消全部监视点
  • trace-mem on/off — 启用/禁用内存地址访问跟踪

5. 通过 DOS 系统加载程序进行调试

在 DOS 系统中,原生具备了调试功能,但我们要让程序从 DOS 规范中规定的内存起始地址 0100h 开始加载。 因此我们需要将代码第一行的“org 07c00h” 改为“org 0100h”,并执行汇编操作生成 COM 文件:

nasm boot.asm –o boot.com

然后下载并安装 DOSBox:https://www.dosbox.com/download.php?main=1。 打开 DOSBox,执行 debug 命令即可进行调试。

5.1. DOS 调试指令

DOS 中所有的数字都是十六进制的,所以你不能指定进制转换及如何显示。 下表是 DOS 的全部调试指令。

DOS 调试指令

指令

简称

参数

说明

assemble

A

[address]

从 CS:0100 地址开始编写汇编代码,不支持宏指令或标签

compare

C

range address

比较两个内存块,如果没有差异,则显示 -

dump

D

[range] [length]

dump 内存范围,如 d c000:0010

enter

E

address [list]

将数据或指令(作为机器代码)直接输入到内存位置,例如 e ffcb d2 将内存 ffcb 位置修改为 d2

fill

F

range list

用连续重复的值填充内存范围,例如 f 100 12f ’BUFFER’ 将地址 100 到 12f 之间的区域循环用 BUFFER 填充

go

G

[=address] [addresses]

运行直到断点或指定的内存地址

hex

H

value1 value2

十六进制加法操作

input

I

port

进行 IO 操作

load

L

[address] [drive] [firstsector] [number]

加载指定内存地址、驱动器、扇区 number 数量的值到内存中

move

M

range address

将指定范围内的所有字节复制到新地址,例如 m 7c00 7cff 600 将内存 7c00 到 7cff 范围内的信息复制到内存地址 600 起始的位置

name

N

[pathname] [arglist]

加载指定的 com 文件

output

O

port byte

进行 IO 操作

proceed

P

[=address] [number]

单步执行,但跳过函数

quit

Q

 

退出调试

register

R

[register]

显示所有寄存器及存储的内容

search

S

range list

在内存范围内查询一个或多个字节值,例如 s fe00:0 ffff "BIOS" 命令在 fe00:0 ffff 范围内查找了 BIOS 字符串

trace

T

[=address] [number]

单步执行,进入函数

unassemble

U

[range]

反汇编指定内存范围内的指令,默认从 0010 开始进行反汇编 32 字节

write

W

[address] [drive] [firstsector] [number]

将程序从 DEBUG 中保存到硬盘

6. bochs 结合 freedos

6.1. FreeDos 的开启

bochs 如何模拟 dos 环境,加载我们的程序呢? 我们可以下载 bochs 官方提供的 FreeDos 镜像:http://bochs.sourceforge.net/guestos/freedos-img.tar.gz。 解压后,得到 FreeDos 的软盘镜像:a.img,将该文件路径配置到 bochsrc 的 floppya 配置项中,就可以打开 Dos 系统了。 为了区分,我们将 a.img 重命名为 freedos.img。

6.2. Dos 程序加载

可是在虚拟机中的 FreeDos 系统,我们要如何才能加载宿主机上我们要调试的系统呢? 只要把需要调试的系统烧录到另一个软盘镜像上,作为 bochs 另一个盘启动,位于 floppya 中的 FreeDos 系统就可以找到这个文件了。

6.2.1. 生成软盘镜像

首先我们需要创建一个软盘镜像。 bochs 提供了 bximage 命令, 用来生成磁盘镜像文件:

6.2.2. 格式化软盘

a.img 是一个镜像文件,我们需要将这个镜像装载为软盘,才能够完成镜像的格式化,并拷入我们需要的程序文件。 这就需要使用 Linux 中的 loop 设备,类似于 Windows 的虚拟光驱。 如果你是在 windows 环境下使用 WSL,那么很遗憾,当前版本 wsl 不支持 loop 设备,你可以下载虚拟软驱加载 a.img 完成这些操作。 在 Linux 环境下,依次执行下列命令格式化我们生成的软盘镜像:

dd if=/dev/null of=a.img bs=512 count=1 conv=notrunc # 写入空白内容 sudo losetup /dev/loop0 a.img # 将 a.img 更改为 loop device sudo mkfs.msdos /dev/loop0 # 格式化为 DOS 文件系统格式 sudo fsck.msdos /dev/loop0 # 检视文件系统 sudo losetup -d /dev/loop0 # 删除临时 loop device

执行 file a.img,可以看到下面的信息,说明已经格式化完成:

a.img: DOS floppy 1440k, x86 hard disk boot sector

6.2.3. 汇编程序

我们需要按照上面说的,将代码第一行的“org 07c00h”改为“org 0100h”,并执行汇编操作生成 COM 文件:

nasm boot.asm –o boot.com

6.2.4. 将 boot.com 复制到软盘

然后执行下面命令将 boot.com 复制到软盘 a.img 中:

sudo mkdir /mnt/floppy # 创建挂载点 sudo mount -o loop a.img /mnt/floppy # 挂载 loop 设备 a.img sudo cp boot.com /mnt/floppy # 将 boot.com 复制到 a.img sudo umount /mnt/floppy # 接触挂载

6.2.5. 配置 bochsrc

代码语言:javascript
复制
###############################################################
# Configuration file for Bochs
###############################################################

# how much memory the emulated machine will have
megs: 32

# filename of ROM images
#romimage: file=/usr/local/share/bochs/BIOS-bochs-latest
romimage: file=$BXSHARE/BIOS-bochs-latest
#vgaromimage: /usr/local/share/vgabios/vgabios.bin
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest

# what disk images will be used
floppya: 1_44=C:\Debin\Workspace\code\oranges\freedos\freedos.img, status=inserted
floppyb: 1_44=C:\Debin\Workspace\code\oranges\freedos\a.img, status=inserted

# choose the boot disk.
boot: floppy

# where do we send log messages?
# log: bochsout.txt

# disable the mouse
mouse: enabled=0

# enable key mapping, using US layout as default.
keyboard: keymap=$BXSHARE/keymaps/x11-pc-us.map
mouse: enabled=1
mouse: type=imps2, enabled=1
mouse: type=serial, enabled=1
mouse: enabled=0, toggle=ctrl+f10

6.2.6. 执行程序

运行 bochs,即可打开 Dos 系统,执行 b:\boot.com。

7. 参考资料

http://bochs.sourceforge.net/ http://bochs.sourceforge.net/doc/docbook/user/internal-debugger.html。 https://www.dosbox.com/ https://www.gsp.com/cgi-bin/man.cgi?section=5&topic=bochsrc。 https://montcs.bloomu.edu/Information/LowLevel/DOS-Debug.html。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小脑斧科技博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 引言
  • 2. 反汇编
  • 3. 开源虚拟机 bochs 的调试功能
    • 3.1. bochs 的安装
      • 3.2. bochs 配置
        • 3.3. 启动 bochs
          • 3.3.1. unix 环境
          • 3.3.2. windows 环境
      • 4. bochs 调试指令
        • 4.1. 断点
          • 4.2. 执行控制
            • 4.3. 信息查看
              • 4.4. 操作内存
                • 4.4.1. 参数取值
                • 4.4.2. 单位大小取值
                • 4.4.3. 打印方式取值
              • 4.5. 内存监控
              • 5. 通过 DOS 系统加载程序进行调试
                • 5.1. DOS 调试指令
                • 6. bochs 结合 freedos
                  • 6.1. FreeDos 的开启
                    • 6.2. Dos 程序加载
                      • 6.2.1. 生成软盘镜像
                      • 6.2.2. 格式化软盘
                      • 6.2.3. 汇编程序
                      • 6.2.4. 将 boot.com 复制到软盘
                      • 6.2.5. 配置 bochsrc
                      • 6.2.6. 执行程序
                  • 7. 参考资料
                  相关产品与服务
                  专用宿主机
                  专用宿主机(CVM Dedicated Host,CDH)提供用户独享的物理服务器资源,满足您资源独享、资源物理隔离、安全、合规需求。专用宿主机搭载了腾讯云虚拟化系统,购买之后,您可在其上灵活创建、管理多个自定义规格的云服务器实例,自主规划物理资源的使用。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档