本文以windows平台为例
在开始之前,我假设你已经安装好了bochs.
用到工具
- bochs2.6.9
官网:http://bochs.sourceforge.net/
我在写这篇文字的时候,官网提示在正在迁移到新数据中心。上不了
- nasm编译器
官网:
www.nasm.us
笔者打开不了官网,为方便打开不了官网的朋友下载:
http://download.csdn.net/download/chprain/10252189
- virtualbox虚拟机
https://www.virtualbox.org/wiki/Downloads
- vhdw(笔者用C语言写的辅助工具)
http://download.csdn.net/download/chprain/10252188
在bochs程序目录下新建一个bochsrc.txt文件
比如笔者的目录为:D:\Program Files (x86)\Bochs-2.6.9
配置文件说明
# "#"是注释(comment)
# 分配内存megs参数[megs: 128 分配128MB内存,最大是2048]不被赞成使用
# 使用memory替代
# guest 分配给模拟器客户端的内存大小
# host 从guest分配给主机的内存大小,实际分配可能比guest小,如果用到了
# 更多的内存将会动态加入,但访问不能大于guest内存大小.
# memory 没有内存大小限制,限制的是CPU可访问内存最大大小(即CPU地址总线宽度)
memory: guest=256,host=128
# 配置ROM BIOS,ROM BIOS将控制计算机首次启动的功能(BIOS的固件)
# file:ROM BIOS二进制文件路径,这个参数下面不再解说
romimage: file=BIOS-bochs-latest
# VGA ROM 的映象文件 一般是被映射到内存地址0xC0000处,相当于我们的显卡
vgaromimage: file=VGABIOS-elpin-2.40
#使用软驱 floppy_ ,"_"可以是a,b,c,d...
#例子:软驱a,b 大小为1.44MB
# 参数:status 有两种分别为
# inserted(软盘插入软驱),ejected(软盘未插入软驱)。
floppya: 1_44=floppya.img, status=inserted
floppyb: 1_44=floppyb.img, status=inserted
# ata是一个接口 可以是ata0,ata1,ata2,ata3,用来控制硬盘(disk)和光驱(cdrom)
#ioaddr1 分配主盘的io端口地址 .....
#ioaddr2 分配从盘的io端口地址 .....
#irg 中断请求号(当发生中断时,对应的中断向量)
#学过硬盘端口读写的朋友应该知道主盘对应端口(0x1f0~0x1f7)
#从盘对应对口(0x3f0~0x3f7)
ata0: enabled=1,ioaddr1=0x1f0, ioaddr2=0x3f0,irq=14
#ata[0-3]-master 定义设备类型和特征
#type 连接设备的类型[disk(硬盘)|cdrom(光驱)]
#path 虚拟镜像路径(我用的是virtualbox虚拟机的虚拟硬盘)
#cylinders 柱面数(type为硬盘是才有这个参数)
#heads 每柱面拥有的磁道数(type为硬盘是才有这个参数)
#spt 没磁道的扇区数量(type为硬盘是才有这个参数)
ata0-master: type=disk,path=myvhd.vhd, cylinders=103, heads=12, spt=17
#设置启动顺序 1.硬盘,2.软驱(配置过BIOS启动项的朋友肯定知道)
boot: disk,floppy
#日志输出 log: 日志路径
log: bochslog.txt
#设置鼠标不可用 ,如果enabled不为0那么bochs会发送鼠标事件到仿真机上
#因为是字符界面,无需鼠标
mouse: enabled=0
#设置键盘
#type 键盘类型
#keymap 键盘映射文件
keyboard: type=mf,keymap=keymaps/x11-pc-us.map
我们可以看到,所有的配置文件我们都没有写绝对路径,我们只是写了一个名称,比如键盘映射文件keymaps/x11-pc-us.map,我们可以在bochs安装目录的子目录keymaps中找到.所以我们用的是相对路径,相对的是bochs安装目录路径.
好了我们来写一个汇编程序,让它运行,笔者用的是nasm编译器,你也可以用其他,让他仅生产汇编代码的二进制文件即可(即没有任何附加代码,你写什么就是什么,这样才能裸机运行).
例子:hello,world
org 0x7c00 ;汇编地址从0x7c00开始
;我们知道BIOS固件(BIOS ROM)会把我们的程序加载到0x7c00物理地址处开始执行.
mov ax,0xb800 ;显存段地址
mov ds,ax
xor bx,bx
mov byte [bx],'h' ;字符
inc bx
mov byte [bx],2 ;字符属性
inc bx
mov byte [bx],'e' ;字符
inc bx
mov byte [bx],2 ;字符属性
inc bx
mov byte [bx],'l' ;字符
inc bx
mov byte [bx],2 ;字符属性
inc bx
mov byte [bx],'l' ;字符
inc bx
mov byte [bx],2 ;字符属性
inc bx
mov byte [bx],'o' ;字符
inc bx
mov byte [bx],2 ;字符属性
inc bx
mov byte [bx],',' ;字符
inc bx
mov byte [bx],2 ;字符属性
inc bx
mov byte [bx],'w' ;字符
inc bx
mov byte [bx],2 ;字符属性
inc bx
mov byte [bx],'o' ;字符
inc bx
mov byte [bx],2 ;字符属性
inc bx
mov byte [bx],'r' ;字符
inc bx
mov byte [bx],2 ;字符属性
inc bx
mov byte [bx],'d' ;字符
inc bx
mov byte [bx],2 ;字符属性
; $当前汇编地址
jmp $
; $$ 开始汇编地址 ,为了确保512字节对齐
; 因为我们要写入主引导扇区才能运行
;主引导扇区最后两个字符为0x55,0xaa
;times 重复多少次 比如:times 10 db 1 ;重复10次 db 1
times 510-($-$$) db 0
db 0x55,0xaa
控制下执行编译,编译命令如下:
nasm -f bin hello.asm -o boot.bin
源码下载地址:http://download.csdn.net/download/chprain/10252188
我用C语言写了一个vhd写入二进制文件内容的控制台程序,笔者也可以自己写一个,非常简单,由于篇幅关系,我把源码上传,就不贴出来了.
这个工具名称是vhdw
;工具使用说明
写进vhd文件命令(第一个扇区,从0开始,不要误会,这是文件,虽然磁盘规定扇区从1开始,0可以省略,默认是第一个扇区)
vhdw D:\boot.bin 0
在win7及其以上的系统,请用管理员权限打开bochs程序目录下的bochsdbg.exe
如果运行正常的话,我们可以看到第一个指令是: jmpf 0xf000:e05b
我们知道,最终他会把我们的程序加载到0x7c00处执行
- 运行:c (直到遇到断点或错误暂停)
是不是在我们的第一条指令暂停了下来,好了,下面你可以单步跟踪了,单步跟踪指令是:
- 单步步过:n
- 单步步入:s
u 0x7c00 0x7d00
以16进制从0x7c00显示16个字节数据
x /16bx 0x7c00
已经不可在bochs2.6.9用的info指令
寄存器查看
在virtual运行也是可以的只要把文件写进创建好虚拟机的vhd磁盘就好了,我直接贴图了.(记得创建磁盘的时候选vhd并且要选固定大小,操作系统就选不知道不知道,因为我们自己写的嘛).