书上得来终觉浅,绝知此事须躬行
bochs是一个不错的模拟器,仅以此文记录一些使用方法。
安装bochs
这个问题看似很简单,但是实际上用的时候你会发现一个问题。在ubuntu上你要这么装:
apt-get install bochs
apt-get install bochs-x
如果不装第二个,执行的时候会报一个错。
>>PANIC<< dlopen failed for module ‘x’: file not found
运行最简单的一个MBR
bochs的运行很简单,执行如下命令即可。
bochs -f bochsrc
关键信息就在这个bochsrc的配置文件中了。这里贴出一个最简单,只运行一个MBR的配置文件。
###############################################################
# Configuration file for Bochs
###############################################################
# how much memory the emulated machine will have
megs: 32
# filename of ROM images
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/vgabios/vgabios.bin
# what disk images will be used
floppya: 1_44=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_mapping: enabled=1, map=/usr/share/bochs/keymaps/x11-pc-us.map
其中我关心的是启动选项和启动盘的选择。
最简单写一个MBR的方法可以参考这两个文章,自己动手写操作系统 和 跟我一起写操作系统(一)
完整例子的文件
我把我使用的相关文件给出,方便有兴趣的同学使用。
boot.asm – MBR代码
org 07c00h ; 告诉编译器程序加载到7c00处
mov ax, cs
mov ds, ax
mov es, ax
call DispStr ; 调用显示字符串例程
jmp $ ; 无限循环 $代表当前地址
DispStr:
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, msgLen ; CX = 串长度
mov ax, 01301h ; AH = 13, AL = 01h
mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
mov dl, 0 ; 将DL中的ASCII码显示到屏幕,将'\0'送到DL中,并显示
int 10h ; 10h 号中断
ret ; 返回到调用处
BootMessage: db "Hello, OS world!"
msgLen: equ $ - BootMessage
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55 ; 结束标志
makefile – 制作带有MBR的软盘
all: a.img
a.img: boot.asm
nasm boot.asm -o boot.bin
dd if=boot.bin of=a.img
dd if=/dev/zero of=a.img seek=1 bs=512 count=2879
clean:
rm -f a.img boot.bin
bochsrc – 运行bochs的配置文件
见上文
vm_start.sh – 启动MBR
bochs -f bochsrc
有了这些,大家就可以运行起来了。虽然这个非常简单,但能跑起来感觉还是很棒的。
尝试调试MBR
使用bochs的关键原因就是因为bochs有调试功能。 那就先来拿这个MBR来做一个简单的实验。
bochs -f bochsrc
启动后,在linux环境上,就会停在那里。
在 0x7c00 处设置断点
至于为什么可以参看跟我一起写操作系统(一), 我反正也讲不清楚~
pb 0x7c00
continue
设置完断点就让他继续执行吧。
c
反汇编 0x7c00 0x7c1e
这个例子太简单,我们就简单看一下0x7c00内存上的代码是不是我们写入的代码。
可以看到,这个就是我们写入boot.asm的代码。
查看寄存器
再看一下现在cs段和rip:
sreg
r
确认了下一条指令是要执行 0x0000: 0x7c00地址。
用bochs调试启动初期的内核
制作启动iso
其实这个很简单,只要在内核源代码树下执行 make isoimage就可以了。
但是需要记住一点,把ldlinux.c32也拷贝过去。这个是在 IOSLINUX 提到的。
对于5.00版本以上的,就要把ldlinux.32拷贝过去。否则就会在启动中报找不到这个文件。
所以相应的把编译稍稍改变一下。
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index be8e688..72510fe 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -115,7 +115,7 @@ $(obj)/compressed/vmlinux: FORCE
FDARGS =
# Set this if you want an initrd included with the
# bzdisk/fdimage/isoimage kernel
-FDINITRD =
+FDINITRD = /boot/initrd.img-4.7.0+
image_cmdline = default linux $(FDARGS) $(if $(FDINITRD),initrd=initrd.img,)
@@ -174,11 +174,12 @@ isoimage: $(obj)/bzImage
if [ -f '$(FDINITRD)' ] ; then \
cp '$(FDINITRD)' $(obj)/isoimage/initrd.img ; \
fi
mkisofs -J -r -o $(obj)/image.iso -b isolinux.bin -c boot.cat \
-no-emul-boot -boot-load-size 4 -boot-info-table \
$(obj)/isoimage
isohybrid $(obj)/image.iso 2>/dev/null || true
rm -rf $(obj)/isoimage
bzlilo: $(obj)/bzImage
if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
改动了两个地方: 添加了initrd。
看到这么一个补丁patch。
bochs配置文件
###############################################################
# Configuration file for Bochs
###############################################################
debugger_log: debugger.log
# how much memory the emulated machine will have
megs: 512
# filename of ROM images
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/vgabios/vgabios.bin
# what disk images will be used
ata0-master: type=disk, path="fedora.img", mode=flat, cylinders=20317, heads=16, spt=63
ata0-slave: type=cdrom, path="image.iso", status=inserted
# choose the boot disk.
#boot: c
boot: cdrom
# where do we send log messages?
log: bochsout.txt
# disable the mouse
mouse: enabled=0
# enable key mapping, using US layout as default.
#keyboard_mapping: enabled=1, map=/usr/share/bochs/keymaps/x11-pc-us.map
0x7c00的断点
好了,这里就和普通的调试一样了。
具体的调试,会在另一篇文章中细说。