分享

Bochs虚拟机下载与使用教程bochs虚拟机(Bochs最大的优势就是可以对操作系统进行调试)

 山峰云绕 2023-09-20

1.前言

最近正在学习自制操作系统的相关内容,教程里说最好使用Bochs虚拟机来运行操作系统,于是我百度了一下,竟然没有一篇相关的完整教程,所有就有了这一篇文章

2.Bochs的优势

Bochs最大的优势就是可以对操作系统进行调试,再也不用看着objdumps的结果沉思了。
同时,使用Borchs做出来的操作系统更可能能在真机上启动,问题是这样:

先要科普一点操作系统开发常识,让我们来看一下计算机的启动过程

  1. BIOS: 按下计算机的开关之后,硬件设备会将寄存器CS设置为0xF000,寄存器IP设置为0xFFF0,这样计算机就从地址0xFFFF0 (CS*10H+IP)开始执行程序,这就是BIOS程序。BIOS程序会进行硬件自检即POST过程,如果没有问题屏幕会显示内存,硬盘,CPU等配置信息。这个过程完成之后,BIOS就会去读取下一个设备的程序来启动计算机,那么下一个设备是什么?你应该记得以前每次重新安装操作系统的时候,都会有一个“Boot Device Priority”的选项,这个选项有软盘、光盘、U盘等存储介质,这个选项就决定了各设备的优先级,先从优先级最高的设备启动。

  2. 主引导记录(MBR):无论你上面选择的是哪一种介质,计算机接下来要做的事情都是一样的:计算机要读取这个设备的第一个扇区共512个字节的数据。如果这个扇区的最后两个字节内容是0x55和0xAA,OK,那就表明这就是用户想用它来启动计算机的设备。否则BIOS会把控制权交给启动顺序中第二个设备,而这512个字节也叫作主引导记录(Master Boot Record)。找到启动设备之后,接下来就有一个很重要的规矩:那就是计算机要把这512个字节读取到内存的0x7C00这个地址,并从这个地址开始逐条运行程序。

问题就出在这最后两个字节内容上,通过二进制编辑工具,如果我们把这两个字节删去或改为0x00,0x00,在各虚拟机上测试的结果还不一样,结果如下:

  1. 将最后2字节启动标记:55,AA修改为:00,00,用软盘方式启动测试:

    Vmware能启动;VirtualBox能启动;Bochs不能启动。

  2. 将最后2字节启动标记:55,AA删除,用软盘方式启动测试:

    Vmware能启动;VirtualBox软盘加载镜像失败(相当于不能启动);Bochs不能启动。

看到没?即使你写的MBR程序有问题,用Vmware和VirtualBox虚拟机来验证根本就发现不了!既然Vmware和VirtualBox虚拟机对非标准化的MRB程序都能成功启动,那说明这两种虚拟机不是绝对的“真机”,至少没有那么严谨。

3.Bochs的下载

3.1.Windows

到Bochs提供的下载站下载
一路next…
安装完毕
把安装路径加到path里面(都开始做操作系统开发了,这等小事就不需要教了吧)

3.2 Linux

在命令行下执行

sudo apt-get -y install gcc
sudo apt-get -y install build-essential
sudo apt-get -y install g++
wget https://udomain.dl./project/bochs/bochs/2.6.8/bochs-2.6.8.tar.gz
tar -zxvf bochs-2.6.8.tar.gz
cd bochs-2.6.8
./configure --prefix=xxx(此处填安装路径,不能有空格) --enable-debugger --enable-disasm --enable-iodebug --enable-x86-debugger --with-x --with-x11
make
make install

同样把安装路径加到path里面

3.Bochs的使用

3.1.bochsrc.bxrc配置文件的使用

在项目目录下创建一个文件,叫做bochsrc.bxrc,里面定义虚拟机的硬件参数,各参数意思以及常用值如下(“#”代表注释,不是必需的;如果用不到,可以去掉某参数)

# 指定虚拟机的内存大小为32M
# 看到sample配置文件中,讲到“MEGS”选项已弃用。请改用“MEMORY”选项。自行决定。
memory:32

# 指定虚拟机的BIOS镜像
romimage: file=(bochs安装路径)/share/bochs/BIOS-bochs-latest
vgaromimage: file=(bochs安装路径)/share/bochs/VGABIOS-lgpl-latest

# 软盘启动及配置(1_44为大小,支持的大小有:
#   2_88 : 2.88MB 3.5 介质
#   1_44 : 1.44MB 3.5 介质
#   1_2 : 1.2MB  5.25 介质
#   720k : 720KB  3.5 介质
#   360k : 360KB  5.25 介质
#   320k : 320KB  5.25 介质
#   180k : 180KB  5.25 介质
#   160k : 160KB  5.25 介质
# )
floppya: 1_44="a.img(这里是软盘镜像文件路径)"
boot: floppy

# 指定日志文件,里面有各种运行时信息(可以不指定)
log: bochsout.txt

# 不使用鼠标(使用则设为1,尽量不使用)
mouse: enabled=0

# 这定义了Bochs内部与cpu相关的参数:
#
# model:
# 从预定义的所有列表中选择要模拟的CPU配置
#
# 可以选择的CPU配置:
#  pentium                    Intel Pentium (P54C)
#  pentium_mmx                Intel Pentium MMX
#  amd_k6_2_chomper           AMD-K6(tm) 3D processor (Chomper)
#  p2_klamath                 Intel Pentium II (Klamath)
#  p3_katmai                  Intel Pentium III (Katmai)
#  p4_willamette              Intel(R) Pentium(R) 4 (Willamette)
#  core_duo_t2400_yonah       Intel(R) Core(TM) Duo CPU T2400 (Yonah)
#  atom_n270                  Intel(R) Atom(TM) CPU N270
#  p4_prescott_celeron_336    Intel(R) Celeron(R) 336 (Prescott)
#  athlon64_clawhammer        AMD Athlon(tm) 64 Processor 2800+ (Clawhammer)
#  athlon64_venice            AMD Athlon(tm) 64 Processor 3000+ (Venice)
#  turion64_tyler             AMD Turion(tm) 64 X2 Mobile TL-60 (Tyler)
#  phenom_8650_toliman        AMD Phenom X3 8650 (Toliman)
#  core2_penryn_t9600         Intel Mobile Core 2 Duo T9600 (Penryn)
#  corei5_lynnfield_750       Intel(R) Core(TM) i5   750 (Lynnfield)
#  corei5_arrandale_m520      Intel(R) Core(TM) i5 M 520 (Arrandale)
#  corei7_sandy_bridge_2600k  Intel(R) Core(TM) i7-2600K (Sandy Bridge)
#  zambezi                    AMD FX(tm)-4100 Quad-Core Processor (Zambezi)
#  trinity_apu                AMD A8-5600K APU (Trinity)
#  ryzen                      AMD Ryzen 7 1700
#  corei7_ivy_bridge_3770k    Intel(R) Core(TM) i7-3770K CPU (Ivy Bridge)
#  corei7_haswell_4770        Intel(R) Core(TM) i7-4770 CPU (Haswell)
#  broadwell_ult              Intel(R) Processor 5Y70 CPU (Broadwell)
#
# reset_on_triple_fault:
# 发生三重故障时重置CPU(强烈建议),而不是继续。
# 请记住,如果您试图在三次故障后继续,模拟将完全是错误的!

# msrs:
# 定义用户CPU型号特定寄存器(MSR)规范的路径。
# 请参阅msrs.def中的示例。
#
# ignore_bad_msrs:
# 忽略Bochs不理解的MSR引用;打印警告消息,而不是生成GP异常。此选项已启用
# 默认情况下启用,但如果启用了可配置的MSR,则不可用。
#
# ips:
# 每秒模拟指令数
# IPS用于校准bochs内的许多与时间相关的事件
# 模拟。例如,更改IPS会影响VGA的频率
# updates:
# 密钥开始自动重播之前的持续时间,以及BogoMips和其他基准的测量。
cpu: ips=15000000
#=======================================================================
# ATA0, ATA1, ATA2, ATA3
# 用于硬盘和光盘的ATA控制器
#
# ata[0-3]: enabled=[0|1], ioaddr1=addr, ioaddr2=addr, irq=number
# 
# 这些选项最多允许4个ATA通道。必须为每个通道指定两个基本IO地址和IRQ。
# 
# ata0和ata1默认启用,其值如下所示
#
# 例子:
#   ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
#   ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
#   ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
#   ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x360, irq=9
#=======================================================================
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14

#=======================================================================
# ATA[0-3]-MASTER, ATA[0-3]-SLAVE
#
# 这定义了所有连接的ATA设备的类型和特征:
#   type=       连接设备的类型[disk(磁盘)|cdrom(光盘)]
#   mode=       [flat|concat|dll|sparse|vmware3|vmware4|undoable|growing|volatile|vpc|vbox|vvfat]仅对磁盘有效
#   path=       软盘文件/目录的路径
#   cylinders=  只对磁盘有效
#   heads=      只对磁盘有效
#   spt=        只对磁盘有效
#   status=     只对光盘有效 [inserted(插入)|ejected(弹出)]
#   biosdetect= MBR引导检测的类型 [auto|cmos|none]
#   translation= bios的翻译类型,仅适用于磁盘 [none|lba|large|rechs|auto]
#   model=      由识别设备命令返回的字符串
#   journal=    可选的文件名,用于 undoable、volatile 和 vvfat 磁盘的 redolog。
#
# 将其指向硬盘镜像文件、光盘iso文件或物理光盘。
# 要创建一个硬盘镜像,试着运行bximage,它将帮助你选择大小,然后建议一个与之相适应的线路。
#
# 在UNIX中,可以使用原始设备作为Bochs硬盘,但我们不推荐。在Windows中没有简单的方法可以这么做。
#
# 在WINDOWS中,光盘应使用盘符+冒号的符号。
# 根据windows和驱动程序的版本,你可能只能访问系统中的 "第一个" 只读光盘。 
# 在MacOSX上,使用path="drive"来访问物理驱动器。
#
# 路径对于硬盘来说是必须的。如果CHS设置为0/0/0,磁盘自动检测对bximage创建的软盘文件有效(柱面使用head=16和spt=63计算)
# 对于其他的硬盘镜像和模式,柱面、磁头和spt是必须的。
# 在所有情况下,软盘镜像文件大小必须正好是C*H*S*512。
#
# 默认的值是:
#   mode=flat, biosdetect=auto, translation=auto, model="Generic 1234"
#
# biosdetect选项目前对bios没有影响。
#
# 例子:
#   ata0-master: type=disk, mode=flat, path=10M.sample, cylinders=306, heads=4, spt=17
#   ata0-slave:  type=disk, mode=flat, path=20M.sample, cylinders=615, heads=4, spt=17
#   ata1-master: type=disk, mode=flat, path=30M.sample, cylinders=615, heads=6, spt=17
#   ata1-slave:  type=disk, mode=flat, path=46M.sample, cylinders=940, heads=6, spt=17
#   ata2-master: type=disk, mode=flat, path=62M.sample, cylinders=940, heads=8, spt=17
#   ata2-slave:  type=disk, mode=flat, path=112M.sample, cylinders=900, heads=15, spt=17
#   ata3-master: type=disk, mode=flat, path=483M.sample, cylinders=1024, heads=15, spt=63
#   ata3-slave:  type=cdrom, path=iso.sample, status=inserted
#=======================================================================
ata0-master: type=cdrom, mode=flat, path="30M.iso(这里填光盘镜像文件路径)"
#ata0-master: type=disk, mode=flat, path="30M.sample", cylinders=615, heads=6, spt=17
#ata0-master: type=disk, mode=flat, path="c.img", cylinders=0 # autodetect
#ata0-slave: type=disk, mode=vvfat, path=/bochs/images/vvfat, journal=vvfat.redolog
#ata0-slave: type=cdrom, path=D:, status=inserted
#ata0-slave: type=cdrom, path=/dev/cdrom, status=inserted
#ata0-slave: type=cdrom, path="drive", status=inserted
#ata0-slave: type=cdrom, path=/dev/rcd0d, status=inserted

3.2.使用bochs启动一个hello world系统

3.2.1.系统源码

随便找了一个hello world系统,使用nasm语言编写:
创建boot.asm文件,写入

mov ax, 0b800h
mov ds, ax

mov byte [0x00],'h'
mov byte [0x02],'e'
mov byte [0x04],'l'
mov byte [0x06],'l'
mov byte [0x08],'o'
mov byte [0x0a],','
mov byte [0x0c],'w'
mov byte [0x0e],'o'
mov byte [0x10],'r'
mov byte [0x12],'l'
mov byte [0x14],'d'
jmp $

times 510-($-$$) db 0
db 0x55,0xaa

times 1474560-($-$$) db 0

很简单吧

3.2.2.准备系统

创建虚拟软盘文件:

bximage -mode=create -fd=1.44M -q os.img

确保系统中安装了nasm(没安装请自行百度)
编译boot.asm文件:

nasm boot.asm -o boot.bin

将boot.bin插入os.img:

dd if=boot.bin of=os.img bs=512 count=1 conv=notrunc

3.2.3.准备bochsrc.bxrc文件

准备的bochsrc.bxrc文件如下:

romimage: file=(bochs安装路径)/share/bochs/BIOS-bochs-latest
vgaromimage: file=(bochs安装路径)/share/bochs/VGABIOS-lgpl-latest

keyboard:keymap=(bochs安装路径)/share/bochs/keymaps/x11-pc-us.map

# 1.44=磁盘镜像位置
floppya: 1_44="os.img", status=inserted

# 从软盘启动
boot: floppy

# 置鼠标不可用
mouse: enabled=0

megs: 512

3.2.3.开始模拟

bochs -f bochsrc.bxrc
========================================================================
                       Bochs x86 Emulator 2.6.8
                Built from SVN snapshot on May 3, 2015
                  Compiled on Jul  2 2023 at 13:38:20
========================================================================
00000000000i[      ] BXSHARE not set. using compile time default '/home/marscheng/ProgramFiles/bochs-2.6.8/share/bochs'
00000000000i[      ] reading configuration from bochsrc.bxrc
------------------------------
Bochs Configuration: Main Menu
------------------------------

This is the Bochs Configuration Interface, where you can describe the
machine that you want to simulate.  Bochs has already searched for a
configuration file (typically called bochsrc.txt) and loaded it if it
could be found.  When you are satisfied with the configuration, go
ahead and start the simulation.

You can also start bochs with the -q option to skip these menus.

1. Restore factory default configuration
2. Read options from...
3. Edit options
4. Save options to...
5. Restore the Bochs state from...
6. Begin simulation
7. Quit now

Please choose one: [6]

直接enter

Next at t=0
(0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b          ; ea5be000f0
<bochs:1> c

输入c,enter

成功:

4.bochs无法关闭的解决方法

windows就直接用任务管理器
linux的解决方法如下:
先ctrl + z暂停线程
使用ps命令获取bochs线程的pid

kill (线程的pid)

最后

fg

进程就结束了

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多