1.前言最近正在学习自制操作系统的相关内容,教程里说最好使用Bochs虚拟机来运行操作系统,于是我百度了一下,竟然没有一篇相关的完整教程,所有就有了这一篇文章 2.Bochs的优势Bochs最大的优势就是可以对操作系统进行调试,再也不用看着objdumps的结果沉思了。 先要科普一点操作系统开发常识,让我们来看一下计算机的启动过程
问题就出在这最后两个字节内容上,通过二进制编辑工具,如果我们把这两个字节删去或改为0x00,0x00,在各虚拟机上测试的结果还不一样,结果如下:
看到没?即使你写的MBR程序有问题,用Vmware和VirtualBox虚拟机来验证根本就发现不了!既然Vmware和VirtualBox虚拟机对非标准化的MRB程序都能成功启动,那说明这两种虚拟机不是绝对的“真机”,至少没有那么严谨。 3.Bochs的下载3.1.Windows到Bochs提供的下载站下载 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语言编写: 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(没安装请自行百度) 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就直接用任务管理器 kill (线程的pid) 最后 fg 进程就结束了 |
|
来自: 山峰云绕 > 《虚拟机技术硬件平台仿真模拟器》