bochs+nasm:调试小技巧

来源:互联网 发布:ubuntu设置mysql密码 编辑:程序博客网 时间:2024/06/16 18:59
  

   通过断点跟踪源程序,是了解源程序的好方法。试着通过bochs调试nasm程序不短时间了,也总结了一些小技巧,具体见下:

 

   1、lst文件的妙用

   在编译asm文件时,记得同时生成lst文件,这样在调试源程序时,就可以参考lst文件所提供的偏移地址。

 

   2、设置断点b指令和反汇编disasm指令的结合使用

   可以使用CS段基址加上lst文件所提供的断点处代码的偏移地址,得到断点的物理地址,然后使用disasm指令对该物理地址反汇编以验证断点设置是否正确。示例如下:

<bochs:4>n
(0) [0x00000000000325c8] 3224:0388 (unk. ctxt): movax, cs
<bochs:5>sreg
cs:0x3224, dh=0x00009303, dl=0x2240ffff,valid=1
       Data segment, base=0x00032240, limit=0x0000ffff, Read/Write,Accessed
查看lst文件可知jmp指令的偏移地址,假设须在此设置断点,可以如此计算:0x32240+0x0388+0xEC=0x325c8+0xEC=0x326b4

   397 000000008CC8                    mov ax, cs
   ... ...
   490 000000EC66EA000000001000        jmp dword SelectorCode32:0

反汇编0x326b4处的指令,确实为jmp指令
<bochs:6>disasm 0x326b4
000326b4:(                   ): jmp far0010:00000000    ; 66ea000000001000
<bochs:10> b0x326b4
<bochs:11>c
(0) Breakpoint 1, 0x00000000000326b4 in ?? ()
(0) [0x00000000000326b4] 3224:0000000000000474 (unk. ctxt): jmp far0010:00000000

   3、全局描述符表GDT基地址、选择子及显示内存

   执行指令“lgdt [GdtPtr]”后gdtr寄存器将指向全局描述符表GDT基地址,当使用选择子进行跳转时,可以使用显示内存指令X查看该选择子对应的物理基地址。

<bochs:11>c
(0) Breakpoint 1, 0x00000000000326b4 in ?? ()
(0) [0x00000000000326b4] 3224:0000000000000474 (unk. ctxt): jmp far0010:00000000

选择子为0x0010,即描述符索引为0x10,检查GDT基地址为0x32348
<bochs:12>sreg
gdtr:base=0x0000000000032348, limit=0x3f

显示0x32348处的内存信息
<bochs:13> x/32xb 0x32348
[bochs]:
0x0000000000032348<bogus+  0>:   0x00   0x00   0x00   0x00   0x00   0x00   0x00   0x00
0x0000000000032350<bogus+  8>:   0xff   0xff   0x00   0x00   0x00   0x92   0x00   0x00
0x0000000000032358<bogus+  16>:   0x65   0x00   0xd4   0x26   0x03   0x98   0x40   0x00
0x0000000000032360<bogus+  24>:   0xff   0xff   0x3c   0x27   0x03   0x98   0x00    0x00

查看对应描述符索引0x10(即bogus+  16)处对应的描述符,该段描述符对应的段基址为:0x000326d4,即字节7、字节4、字节3和字节2内容串联即可获得段基址。
<bochs:15>disasm 0x326d4
000326d4:(                   ): mov eax,0xd88e0020      ; 66b820008ed8

<bochs:16>n
(0) [0x00000000000326d4] 0010:0000000000000000 (unk.ctxt): mov ax, 0x0020

反汇编结果和单步执行结果相同。

 

   4、设置内存WatchPoints

   lst文件中指令“lodsb”将从内存地址0x32392处读取一个字节,可以在该字节处设置WatchPoints,当程序执行指令"lodsb"时将触发该WatchPoints,类似于断点。

   536 00000028AC                      lodsb
   537 0000002984C0                    test al, al
<bochs:27>watch read 0x32392
read watchpoint at0x0000000000032392 len=1 inserted
<bochs:30>c
00141741995i[CPU0 ] [141741995] Caught read watchpoint
(0) Caught read watch point at 0x0000000000032392
(0) [0x00000000000326fd] 0010:0000000000000029 (unk. ctxt): testal, al

 

   5、局部描述符表LDT和全局描述符表GDT跟踪

<bochs:31>c
(0) [0x000000000003271c] 0010:0000000000000048 (unk.ctxt): jmp far 0004:00000000

从指令"jmp far0004:00000000"可以看出程序将跳转至LDT(因TI位为1)表中描述符索引为0的局部段,使用指令"sreg"检查LDT和GDT段基址

<bochs:32>sreg
ldtr:0x0030, dh=0x00008203, dl=0x27580007,valid=1
gdtr:base=0x0000000000032348, limit=0x3f
<bochs:33> x/64xb 0x32348
0x0000000000032348<bogus+  0>:   0x00   0x00   0x00   0x00   0x00   0x00   0x00   0x00
... ...
0x0000000000032378 <bogus+ 48>:   0x07   0x00   0x58   0x27   0x03   0x82   0x00   0x00
0x0000000000032380 <bogus+ 56>:   0xff   0xff   0x00   0x80   0x0b   0x93   0x00    0x00

由GDT段基址0x32348及选择子0x30可知LDT段基址为:0x032758
<bochs:34> x/16xb 0x32758
0x0000000000032758<bogus+  0>:   0x19   0x00   0x60   0x27   0x03   0x98   0x40   0x00
0x0000000000032760<bogus+  8>:   0x66   0xb8   0x38   0x00   0x8e   0xe8   0xbf   0x80
反汇编0x032758处内存指示的内存地址0x32760,可知LD处的第一条指令
<bochs:35>disasm 0x32760
00032760:(                   ): mov ax, 0x0038

设置断点执行,与设想的一致

<bochs:37> b0x32760
<bochs:38> c
(0)Breakpoint 3, 0x0000000000032760 in ?? ()
(0) [0x0000000000032760] 0004:0000000000000000 (unk. ctxt): mov ax,0x0038

0 0
原创粉丝点击