简介:
本文以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
- -f(format)即编译格式,选择纯二进制bin,这样才不会写进其他代码
- hello.asm 我们要编译的汇编代码文件,这是相对路径,如果提示找不到文件请用绝对路径
- -o 输出文件路径
写进vhd虚拟磁盘
源码下载地址:http://download.csdn.net/download/chprain/10252188
我用C语言写了一个vhd写入二进制文件内容的控制台程序,笔者也可以自己写一个,非常简单,由于篇幅关系,我把源码上传,就不贴出来了.
这个工具名称是vhdw
;工具使用说明
- 在程序目录下建立一个:config.txt
- 在config.txt中写上vhd文件路径,比如:D:\Program Files (x86)\Bochs-2.6.9\myvhd.vhd,不要带换行符和空格
- 可以直接打开vhdw.exe,也可以在控制台输入(在vhdw.exe文件目录,或加入了环境变量,否则要写决定路径) vhdw bin文件 写入扇区.例如 vhdw D:\boot.bin 0 ;在0扇区开始写入boot.bin二进制文件
我编译了的hello.asm在D盘
写进vhd文件命令(第一个扇区,从0开始,不要误会,这是文件,虽然磁盘规定扇区从1开始,0可以省略,默认是第一个扇区)
vhdw D:\boot.bin 0
开始执行调试
在win7及其以上的系统,请用管理员权限打开bochs程序目录下的bochsdbg.exe
如果运行正常的话,我们可以看到第一个指令是: jmpf 0xf000:e05b
我们知道,最终他会把我们的程序加载到0x7c00处执行
- 下断点:b 内存地址 (lb是在线性地址下断点,用法和b相同)
- 运行:c (直到遇到断点或错误暂停)
是不是在我们的第一条指令暂停了下来,好了,下面你可以单步跟踪了,单步跟踪指令是:
- 单步步过:n
- 单步步入:s
s
s 10 #相当于10次 s
- 查看指定内存地址的汇编指令: u 开始地址 结束地址
u 0x7c00 0x7d00
最后运行结果:
![这里写图片描述](https://img-blog.csdn.net/20180215173659815?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hwcmFpbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)其他一些调试指令
- 显示指定内存地址的数据 x查看线性地址,xp 查看物理地址
格式: x(p)/nuf addr -
- n 数据长度
-
- u 数据单元大小 b(1),h(2),w(4),g(8).后面的数字表示字节
-
-
- b BYTE
-
-
-
- h WORD(我也不知为啥用h)
-
-
-
- w DWORD
-
-
-
- g DWORD64
-
-
- f 数据显示格式:x d u o t c
-
-
- x 十六进制
-
-
-
- d 十进制
-
-
-
- u 无符号十进制
-
-
-
- o 八进制
-
-
-
- t 二进制
-
-
-
- c 按照字符显示
-
以16进制从0x7c00显示16个字节数据
x /16bx 0x7c00
- 查看信息指令:info
-
- info b 显示所有断点状态
-
- info cpu 查看全部cpu寄存器信息
-
- info idt 查看保护模式中断向量描述表
-
- info ivt 查看实模式下的中断向量表
-
- info gdt查看全局描述符表
-
- info tss 查看当前任务状态段
-
- info flags 查看标志寄存器内容
已经不可在bochs2.6.9用的info指令
-
- info program 查看程序的执行状态 (无法使用!)
-
- info r|reg|rigisters 查看寄存器内容(无法使用!)
-
- info cr 查看CR0-CR4寄存器状态 (无法使用)
寄存器查看
-
- r 查看通用寄存器
-
- cr 查看CR控制寄存器
-
- sreg 查看段寄存器
-
- creg 查看控制寄存器
-
- dreg 查看调试寄存器
在virtualBox虚拟机上运行
在virtual运行也是可以的只要把文件写进创建好虚拟机的vhd磁盘就好了,我直接贴图了.(记得创建磁盘的时候选vhd并且要选固定大小,操作系统就选不知道不知道,因为我们自己写的嘛).