Bochs是一个给力的东西.. 在准备自己写点想在裸机上跑的东西. 这个工具是必备的.

Bochs继承自Unix和Windows不一路. 命令和Windbg之流完全不是一个款式, 好在命令就那么几十条, 很快就能够上手. 不需要太多时间就可以全部掌握..

另外一个就是配置文件的问题了. 配置文件也很简单. 里面已经有了Linux的Demo直接就可以拿来用. 只需要修改下这两行

1
2
        floppya: 1_44=MSDOS71.IMG, status=inserted  
        floppyb: 1_44=CodeFile.IMG, status=inserted

修改成自己想要启动的软盘就可以了. 另外在下面设置下启动软盘, 是这句
        boot: a
那么就可以开始跑了. 本来这个配置文件也简单没有什么好说的, 但是有一个比较给力的地方需要说下. 在Windows上做开发的时候, 对它的Int 3 一直是爱不释手,, 只要写个程序里面嵌入一句Int 3 那么Windbg就自动绑上去了. 真给力.. 开始接触Bochs的时候我就在想, Bochs里面有没有这个东西呢? 果然啊, 也是又的, 不过不是Int 3了, 是这么一句代码
        xchg bx, bx
只要在自己想中断的地方加入这个语句就OK了. 当然配置文件中不要忘记加这么一句话.
        #断点开启(这句是很重要的遇到xchg bx,bx则暂停
        magic_break: enabled=1

这一下又觉得这世界美好了一些.. 再转载点, Bochs的命令..

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
[执行控制]
c|cont                  向下执行,相当于WinDBG的"g"。
s|step|stepi [count]    单步执行,相当于WinDBG的"t",count 默认为 1。
p|n|next                单步执行,类似于WinDBG的"p"。
q|quit|exit             退出调试,同时关闭虚拟机。
Ctrl-C                  结束执行状态,返回调试器提示符。
Ctrl-D                  if at empty line on command line, exit
                        (至少在Windows版本中我没有发现Ctrl-D有什么功能)

[执行断点]
vb|vbreak [seg:off]         在虚拟地址上下断点。
lb|lbreak [addr]            在线性地址上下断点,相当于WinDBG的"bp"。
pb|pbreak|b|break [addr]    在物理地址上下断点。(为了兼容GDB的语法,地址前
                            可以加上一个"*")。
blist                       显示断点状态,相当于WinDBG的"bl"。
bpd|bpe [num]               禁用/启用断点,WinDBG的"be"和"bd"。num是断
                            点号,可以用blist命令查询。
d|del|delete [num]          删除断点,相当于WinDBG的"bc"。mum是断点号,可
                            以用blist命令查询。
[读写断点]
watch read [addr]       设置读断点。
watch write [addr]      设置写断点。
unwatch read [addr]     清除读断点。
unwatch write [addr]    清除写断点。
watch                   显示当前所有读写断点。
unwatch                 清除当前所有读写断点。
watch stop|continue     开关选项,设置遇到读写断点时中断下来还是显示出来但
                        是继续运行。

[内存操作]
x  /nuf [addr]  显示线性地址的内容
xp /nuf [addr]  显示物理地址的内容
    n           显示的单元数
    u           每个显示单元的大小,u可以是下列之一:
                    b BYTE
                    h WORD
                    w DWORD
                    g DWORD64
                    注意: 这种命名法是按照GDB习惯的,而并不是按照inter的规范。

    f           显示格式,f可以是下列之一:
                    x 按照十六进制显示
                    d 十进制显示
                    u 按照无符号十进制显示
                    o 按照八进制显示
                    t 按照二进制显示
                    c 按照字符显示
    n、f、u是可选参数,如果不指定,则u默认是w,f默认是x。如果前面使用过x或
    者xp命令,会按照上一次的x或者xp命令所使用的值。n默认为1。addr 也是一个
    可选参数,如果不指定,addr是0,如过前面使用过x或者xp命令,指定了n=i,
    则再次执行时n默认为i+1。

setpmem [addr] [size] [val]    设置物理内存某地址的内容。

需要注意的是,每次最多只能设置一个DWORD: 这样是可以的:

1
2
3
4
<bochs:1>  setpmem 0x00000000 0x4 0x11223344
<bochs:2> x /4 0x00000000
[bochs]:
0x00000000 <bogus+       0>:    0x11223344 0x00000000 0x00000000 0x00000000

这样也可以:

1
2
3
4
5
6
7
8
9
<bochs:1>  setpmem 0x00000000 0x2 0x11223344
<bochs:2> x /4 0x00000000
[bochs]:
0x00000000 <bogus+       0>:    0x00003344 0x00000000 0x00000000 0x00000000
或者:
<bochs:1>  setpmem 0x00000000 0x1 0x20
<bochs:2> x /4 0x00000000
[bochs]:
0x00000000 <bogus+       0>:    0x00000020 0x00000000 0x00000000 0x00000000

下面的做法都会导致出错:

1
2
3
4
<bochs:1>  setpmem 0x00000000 0x3 0x112233
Error: setpmem: bad length value = 3
<bochs:2>  setpmem 0x00000000 0x8 0x11223344
Error: setpmem: bad length value = 8
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
crc [start] [end]     显示物理地址start到end之间数据的CRC。

[寄存器操作]
set $reg = val              设置寄存器的值。现在版本可以设置的寄存器包括:
                            eax ecx edx ebx esp ebp esi edi
                            暂时不能设置:
                            eflags  cs  ss  ds  es  fs  gs

r|reg|registers reg = val   同上。

dump_cpu                    显示完整的CPU信息。

set_cpu                     设置CPU状态,这里可以设置dump_cpu所能显示出来的
                            所有CPU状态。

[反汇编命令]

u|disas|disassemble [/num] [start] [end]
                                    反汇编物理地址start到end 之间的代码,如
                                    果不指定参数则反汇编当前EIP指向的代码。
                                    num是可选参数,指定处理的代码量。
set $disassemble_size = 0|16|32     $disassemble_size变量指定反汇编使用的段
                                    大小。

set $auto_disassemble = 0|1         $auto_disassemble决定每次执行中断下来的
                                    时候(例如遇到断点、Ctrl-C等)是否反汇
                                    编当前指令。

[其他命令]
trace-on|trace-off      Tracing开关打开后,每执行一条指令都会将反汇编的结果
                        显示出来。

ptime                   显示Bochs自本次运行以来执行的指令条数。

sb [val]                再执行val条指令就中断。val是64-bit整数,以L结尾,形
                        如"1000L"

sba [val]               执行到Bochs自本次运行以来的第val条指令就中断。val是
                        64-bit整数,以L结尾,形如"1000L"

modebp                  设置切换到v86模式时中断。

record [&quot;filename&quot;]     将输入的调试指令记录到文件中。文件名必须包含引号。

playback [&quot;filename&quot;]   回放record的记录文件。文件名必须包含引号。

print-stack [num]       显示堆栈,num默认为16,表示打印的条数。

?|calc                  和WinDBG的"?"命令类似,计算表达式的值。

load-symbols [global] filename [offset]
                        载入符号文件。如果设定了"global"关键字,则符号针
                        对所有上下文都有效。offset会默认加到所有的symbol地
                        址上。symbol文件的格式为:&quot;%x %s&quot;。

[info命令]

info program            显示程序执行的情况。
info registers|reg|r    显示寄存器的信息。
info pb|pbreak|b|break  相当于blist
info dirty              显示脏页的页地址。
info cpu                显示所有CPU寄存器的值。
info fpu                显示所有FPU寄存器的值。
info idt                显示IDT。
info gdt [num]          显示GDT。
info ldt                显示LDT。
info tss                显示TSS。
info pic                显示PIC。
info ivt [num] [num]    显示IVT。
info flags              显示状态寄存器。
info cr                 显示CR系列寄存器。
info symbols            显示symbol信息。
info ne2k|ne2000        显示虚拟的ne2k网卡信息。