IDT系列:(二)中断处理过程,使用bochs调试IDT中的中断服务程序

一、中断处理的过程

 

根据Intel 64 and IA-32 Architectures Software Developer’s Manual 的介绍,在中断或异常产生是,CPU会将当前执行的指令(或下一条指令)在内存中的地址,也就是EIP的值,放入栈中,同时还会放入CS段寄存器和eflags标志寄存器的值等。

根据当前的优先级不同(ring0或ring3,也就是执行与用户态还是内核态)会有较大的不同。如果异常或中断发生时,系统正执行在内核态,那么CPU不会切换栈,直接将EFLAGS、CS、EIP和Error Code压入栈中,如果正执行在非内核态,那么先切换到内核,切换到内核栈,然后依次压入SS、ESP(用户态线程的)、EFLAGS、CS、EIP和Error Code。(上述过程CPU自行完成,操作系统只需要把ISR放到正确的位置等待调用。)然后通过IDT找到对应的ISR 开始执行。

ISR完成处理后通过IRET(IRETD)指令返回到被中断的程序中继续执行即可。

 

 

二、安装配置Bochs和XP Guest系统

 

在上一篇文章中,说了为什么不能使用WinDbg调试ISR。

 

好在我们还有bochs这个带调试功能的软件虚拟机。bochs的调试功能比起WinDbg这个专业调试器来,功能弱了十万八千里。但是,由于bochs是一个软件实现的CPU(对Guest系统来说相当于硬件),比WinDbg要低一个层次,在一些特殊的情况下bochs就能出奇制胜了。bochs是CPU,是一切的主宰,不需要你guest系统给我提供任何支持。

 

安装好bochs以后,可以在bochs中安装windows xp。bochs运行所依赖的一切硬件的配置都是依赖于bxrc配置文件。把安装目录下的bochsrc.bxrc复制一份,双击打开。在下图的对话框里可以编辑配置文件。

IDT系列:(二)中断处理过程,使用bochs调试IDT中的中断服务程序_第1张图片

如果安装xp需要将CPU的主频调高一些(我用的50000000)memory调得合适一些,比如512Mb。在这之前还需要使用安装目录下的bximage.exe创建一个growing的硬盘文件,比如c.img。growing的方式可以避免以后guest系统硬盘不够用。

 

 

IDT系列:(二)中断处理过程,使用bochs调试IDT中的中断服务程序_第2张图片

然后配置“Disk & Boot”选项,挂载上c.img

 

IDT系列:(二)中断处理过程,使用bochs调试IDT中的中断服务程序_第3张图片

 然后配置光盘。需要一个windows xp安装光盘的iso文件,也可以映射到物理光驱。

 

IDT系列:(二)中断处理过程,使用bochs调试IDT中的中断服务程序_第4张图片

 然后配置有cdrom启动。

 

调试过程最好log下来,便于后面分析。在“logfile”选项中配置调试的日志文件。

 IDT系列:(二)中断处理过程,使用bochs调试IDT中的中断服务程序_第5张图片

 

然后save,start就可以开始运行bochs了。

安装过程需要比较漫长的时间,毕竟软件CPU的性能和物理CPU不在一个数量级上。打个球,洗个澡,再吃个饭的时间应该差不多了。
安装好以后注意备份一下,在bochs里安装xp可是一个宏大的系统工程了。然后再把boot选项设置为从disk启动。

安装好以后,就可以使用bochs调试器bochsdbg.exe加载配置文件运行了。在“Bochs Start Menu”里面load然后start。

bochsdbg会停在f000:fff0处(这个时候CPU还没有切换到保护模式)是bios的起始处。
运行命令c(continue)可以继续系统运行。不久windows系统启动。在console里Ctrl-C可以中断运行输入各种调试命令。

 

操作虚拟机的鼠标需要点击按钮,释放时Ctrl+鼠标第三键(滚轮)

 

IDT系列:(二)中断处理过程,使用bochs调试IDT中的中断服务程序_第6张图片

 

三、使用bochs调试观察中断过程

 

先介绍几个调试指令(不是全部,只是在本文中用的的,其他的可以参考help或Bochs的文档)

r 查看通用寄存器

sreg 参看段寄存器(idtr被归到这里了)

creg 参看系统寄存器(cr0等)

x 参看内存(线性地址)

xp 参看内存(物理地址)

pb 通过物理地址下执行断点

lb 通过线性地址下执行断点

setpmem 修改物理内存(Bochs只支持通过物理地址修改内存,不过可以通过info tab参看整个分页表,手工转换一下,而且单步跟踪时Bochs也会同时打印指令对应的物理地址和线性地址)

help 帮助

info idt 参看idt信息

 

Crtl-C中断下XP系统的执行,就可以在Console中输入调试命令。

 

1、静态参看IDT信息


<bochs:5> sreg
es:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=7
 Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
cs:0x0008, dh=0x00cf9b00, dl=0x0000ffff, valid=1
 Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Accessed, 32-bit
ss:0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=7
 Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ds:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=7
 Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
fs:0x0030, dh=0xffc093df, dl=0xf0000001, valid=7
 Data segment, base=0xffdff000, limit=0x00001fff, Read/Write, Accessed
gs:0x0000, dh=0x00001000, dl=0x00000000, valid=0
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=0
tr:0x0028, dh=0x80008b04, dl=0x200020ab, valid=1
gdtr:base=0x000000008003f000, limit=0x3ff
idtr:base=0x000000008003f400, limit=0x7ff

<bochs:6> x /100w 0x8003f400
[bochs]:
0x000000008003f400 <bogus+       0>: 0x0008f19c 0x80538e00 0x0008f314 0x80538e00
0x000000008003f410 <bogus+      16>: 0x0058113e 0x00008500 0x0008f6e4 0x8053ee00
0x000000008003f420 <bogus+      32>: 0x0008f864 0x8053ee00 0x0008f9c0 0x80538e00
0x000000008003f430 <bogus+      48>: 0x0008fb34 0x80538e00 0x0008019c 0x80548e00
0x000000008003f440 <bogus+      64>: 0x00501198 0x00008500 0x000805c0 0x80548e00
0x000000008003f450 <bogus+      80>: 0x000806e0 0x80548e00 0x00080820 0x80548e00
0x000000008003f460 <bogus+      96>: 0x00080a7c 0x80548e00 0x00080d60 0x80548e00
0x000000008003f470 <bogus+     112>: 0x00081450 0x80548e00 0x00081780 0x80548e00
0x000000008003f480 <bogus+     128>: 0x000818a0 0x80548e00 0x000819d8 0x80548e00
0x000000008003f490 <bogus+     144>: 0x00a01780 0x80548500 0x00081b40 0x80548e00
0x000000008003f4a0 <bogus+     160>: 0x00081780 0x80548e00 0x00081780 0x80548e00

... ...

<bochs:3> info idt
Interrupt Descriptor Table (base=0x000000008003f400, limit=2047):
IDT[0x00]=32-Bit Interrupt Gate target=0x0008:0x8053f19c, DPL=0
IDT[0x01]=32-Bit Interrupt Gate target=0x0008:0x8053f314, DPL=0
IDT[0x02]=Task Gate target=0x0058:0x0000113e, DPL=0
IDT[0x03]=32-Bit Interrupt Gate target=0x0008:0x8053f6e4, DPL=3
IDT[0x04]=32-Bit Interrupt Gate target=0x0008:0x8053f864, DPL=3
IDT[0x05]=32-Bit Interrupt Gate target=0x0008:0x8053f9c0, DPL=0
IDT[0x06]=32-Bit Interrupt Gate target=0x0008:0x8053fb34, DPL=0

... ...

<bochs:4> info idt 3
Interrupt Descriptor Table (base=0x000000008003f400, limit=2047):
IDT[0x03]=32-Bit Interrupt Gate target=0x0008:0x8053f6e4, DPL=3

<bochs:8> u 0x8053f6e4 0x8053f6ff
8053f6e4: (                    ): push 0x00000000           ; 6a00
8053f6e6: (                    ): mov word ptr ss:[esp+2], 0x0000 ; 66c74424020000
8053f6ed: (                    ): push ebp                  ; 55
8053f6ee: (                    ): push ebx                  ; 53
8053f6ef: (                    ): push esi                  ; 56
8053f6f0: (                    ): push edi                  ; 57
8053f6f1: (                    ): push fs                   ; 0fa0
8053f6f3: (                    ): mov ebx, 0x00000030       ; bb30000000
8053f6f8: (                    ): mov fs, bx                ; 668ee3
8053f6fb: (                    ): mov ebx, dword ptr fs:0x0 ; 648b1d00000000

 

2、ring0 内核态的INT 3中断

进入Console后单步一次,看一下目前运行在什么地方。


<bochs:3> s
Next at t=5931168643
(0) [0x04f0833f] 0008:00000000bf80533f (unk. ctxt): pop edi                   ; 5f

 

线性地址bf80533f大于80000000应是在内核。

 

反汇编看一下指令

 

<bochs:5> u 0xbf80533f 0xbf805350
bf80533f: (                    ): pop edi                   ; 5f
bf805340: (                    ): pop esi                   ; 5e
bf805341: (                    ): leave                     ; c9
bf805342: (                    ): ret 0x0004                ; c20400
bf805345: (                    ): nop                       ; 90
... ...

 

看一下bf805342对应物理内存中的数据。(s指令时知道 (0) [0x04f0833f] 0008:00000000bf80533f 的内存映射关系)。

 

<bochs:8> xp /20b 0x04f08342
[bochs]:
0x0000000004f08342 <bogus+       0>: 0xc2 0x04 0x00 0x90 0x90 0x90 0x90 0x90
0x0000000004f0834a <bogus+       8>: 0x8b 0xff 0x55 0x8b 0xec 0x83 0xec 0x10
0x0000000004f08352 <bogus+      16>: 0x56 0x8b 0xf1 0x8b

 

将 bf805342: ret 0x0004 修改为int 3

 

<bochs:9> setpmem 0x04f08342 1 0xcc

 

看一下修改的结果

 

<bochs:11> u 0xbf80533f 0xbf805350
bf80533f: (                    ): pop edi                   ; 5f
bf805340: (                    ): pop esi                   ; 5e
bf805341: (                    ): leave                     ; c9
bf805342: (                    ): int3                      ; cc
bf805343: (                    ): add al, 0x00              ; 0400
... ...

 

中断之前的栈
<bochs:15> x /100w rsp
[bochs]:
0x00000000f78807b8 <bogus+       0>: 0xf7880808 0xe13b1008 0x00000000 0x00000000
0x00000000f78807c8 <bogus+      16>: 0x00000001 0x00000001 0xf7880818 0xbf808ae6
0x00000000f78807d8 <bogus+      32>: 0xf78807f8 0xe13b1008 0x81f187d8 0x00000001
0x00000000f78807e8 <bogus+      48>: 0x00000000 0x00000000 0x00000001 0x00000001
0x00000000f78807f8 <bogus+      64>: 0x00000000 0x00000000 0x00000001 0x00000001
0x00000000f7880808 <bogus+      80>: 0x820c92a8 0xe13b1008 0x00000001 0xe183c918
0x00000000f7880818 <bogus+      96>: 0xf788084c 0xbf80d31c 0x81f187d8 0xe13b1008
0x00000000f7880828 <bogus+     112>: 0x8052890c 0x820c92a8 0xe13b1008 0x00000001
0x00000000f7880838 <bogus+     128>: 0xf7880894 0xf7880864 0xe18c5008 0x00000000

... ...
单步到执行到int 3

<bochs:20> s
Next at t=5931168646
(0) [0x04f08342] 0008:00000000bf805342 (unk. ctxt): int3                      ; cc

 

int 3 之前寄存器和栈的情况。

 

<bochs:21> r
rax: 0x00000000:f78807c0 rcx: 0x00000000:00000001
rdx: 0x00000000:00000001 rbx: 0x00000000:e18c5008
rsp: 0x00000000:f78807d4 rbp: 0x00000000:f7880818
rsi: 0x00000000:e13b1008 rdi: 0x00000000:f7880808
r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
r10: 0x00000000:00000000 r11: 0x00000000:00000000
r12: 0x00000000:00000000 r13: 0x00000000:00000000
r14: 0x00000000:00000000 r15: 0x00000000:00000000
rip: 0x00000000:bf805342
eflags 0x00000286: id vip vif ac vm rf nt IOPL=0 of df IF tf SF zf af PF cf
<bochs:22> x /100w rsp
[bochs]:
0x00000000f78807d4 <bogus+       0>: 0xbf808ae6 0xf78807f8 0xe13b1008 0x81f187d8
0x00000000f78807e4 <bogus+      16>: 0x00000001 0x00000000 0x00000000 0x00000001
0x00000000f78807f4 <bogus+      32>: 0x00000001 0x00000000 0x00000000 0x00000001
0x00000000f7880804 <bogus+      48>: 0x00000001 0x820c92a8 0xe13b1008 0x00000001
0x00000000f7880814 <bogus+      64>: 0xe183c918 0xf788084c 0xbf80d31c 0x81f187d8
0x00000000f7880824 <bogus+      80>: 0xe13b1008 0x8052890c 0x820c92a8 0xe13b1008
0x00000000f7880834 <bogus+      96>: 0x00000001 0xf7880894 0xf7880864 0xe18c5008
0x00000000f7880844 <bogus+     112>: 0x00000000 0x00000000 0xf788086c 0xbf81f825
0x00000000f7880854 <bogus+     128>: 0xe13b1008 0x00000001 0x00000000 0x00000000
0x00000000f7880864 <bogus+     144>: 0x0006f2e4 0xbf80cf90 0xf7880888 0xbf80d003


执行int 3,程序跳转到了 ISR 3 8053f6e4
<bochs:23> s
Next at t=5931168647
(0) [0x0053f6e4] 0008:000000008053f6e4 (unk. ctxt): push 0x00000000           ; 6a00

 

寄存器和栈变化了:


<bochs:24> r
rax: 0x00000000:f78807c0 rcx: 0x00000000:00000001
rdx: 0x00000000:00000001 rbx: 0x00000000:e18c5008
rsp: 0x00000000:f78807c8 rbp: 0x00000000:f7880818
rsi: 0x00000000:e13b1008 rdi: 0x00000000:f7880808
r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
r10: 0x00000000:00000000 r11: 0x00000000:00000000
r12: 0x00000000:00000000 r13: 0x00000000:00000000
r14: 0x00000000:00000000 r15: 0x00000000:00000000
rip: 0x00000000:8053f6e4
eflags 0x00000086: id vip vif ac vm rf nt IOPL=0 of df if tf SF zf af PF cf
<bochs:25> x /100w rsp
[bochs]:
0x00000000f78807c8 <bogus+       0>: 0xbf805343 0x00000008 0x00000286 0xbf808ae6
0x00000000f78807d8 <bogus+      16>: 0xf78807f8 0xe13b1008 0x81f187d8 0x00000001
0x00000000f78807e8 <bogus+      32>: 0x00000000 0x00000000 0x00000001 0x00000001
0x00000000f78807f8 <bogus+      48>: 0x00000000 0x00000000 0x00000001 0x00000001
0x00000000f7880808 <bogus+      64>: 0x820c92a8 0xe13b1008 0x00000001 0xe183c918
0x00000000f7880818 <bogus+      80>: 0xf788084c 0xbf80d31c 0x81f187d8 0xe13b1008
... ...

 

 

CPU 在执行int 3时入栈的内容为 0xbf805343 0x00000008 0x00000286 共三个dword 其中 0xbf805343是产生异常的指令的下一条指令(3号中断是Trap类型),0x00000008是CS寄存器的值,0x00000286是eflags寄存器的值。
由于int 3指令也是在ring0执行的,在这个异常过程中没有优先级的切换,所以没有切换栈,入栈的内容只有三个。

继续执行可以调试观察ISR过程


<bochs:26> trace on
Tracing enabled for CPU0
<bochs:27> s 100
(0).[5931168647] [0x0053f6e4] 0008:000000008053f6e4 (unk. ctxt): push 0x00000000           ; 6a00
(0).[5931168648] [0x0053f6e6] 0008:000000008053f6e6 (unk. ctxt): mov word ptr ss:[esp+2], 0x0000 ; 66c74424020000
(0).[5931168649] [0x0053f6ed] 0008:000000008053f6ed (unk. ctxt): push ebp                  ; 55
(0).[5931168650] [0x0053f6ee] 0008:000000008053f6ee (unk. ctxt): push ebx                  ; 53
(0).[5931168651] [0x0053f6ef] 0008:000000008053f6ef (unk. ctxt): push esi                  ; 56
(0).[5931168652] [0x0053f6f0] 0008:000000008053f6f0 (unk. ctxt): push edi                  ; 57
(0).[5931168653] [0x0053f6f1] 0008:000000008053f6f1 (unk. ctxt): push fs                   ; 0fa0
(0).[5931168654] [0x0053f6f3] 0008:000000008053f6f3 (unk. ctxt): mov ebx, 0x00000030       ; bb30000000
(0).[5931168655] [0x0053f6f8] 0008:000000008053f6f8 (unk. ctxt): mov fs, bx                ; 668ee3
(0).[5931168656] [0x0053f6fb] 0008:000000008053f6fb (unk. ctxt): mov ebx, dword ptr fs:0x0 ; 648b1d00000000
(0).[5931168657] [0x0053f702] 0008:000000008053f702 (unk. ctxt): push ebx                  ; 53
(0).[5931168658] [0x0053f703] 0008:000000008053f703 (unk. ctxt): sub esp, 0x00000004       ; 83ec04
... ...

略。

 

3、ring3 用户态下的INT 3中断。

 

下面我们可以在ring 3 状态下产生中断,看看优先级变化时的异常处理。

重启bochs,启动XP Ctrl-C尝试停在ring 3(如果不是Ring 3 多尝试几次,CPU还是有很大比例的时间运行在ring 3态的)
如果暂停时eip线性地址小于0x80000000就是在ring 3态下

在ring 3态下的程序重复上述过程,观察int 3前后的变化。

 

<bochs:9> r
rax: 0x00000000:1e7a18d1 rcx: 0x00000000:4d532745
rdx: 0x00000000:13f91976 rbx: 0x00000000:25dc3f3b
rsp: 0x00000000:0063efc8 rbp: 0x00000000:ffffffe0
rsi: 0x00000000:0009f7e0 rdi: 0x00000000:0009f870
r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
r10: 0x00000000:00000000 r11: 0x00000000:00000000
r12: 0x00000000:00000000 r13: 0x00000000:00000000
r14: 0x00000000:00000000 r15: 0x00000000:00000000
rip: 0x00000000:68021d3b
eflags 0x00000202: id vip vif ac vm rf nt IOPL=0 of df IF tf sf zf af pf cf

<bochs:10> x /100w rsp
[bochs]:
0x000000000063efc8 <bogus+       0>: 0x0063efd8 0x00000020 0x0009f7e0 0x0009f7f0
0x000000000063efd8 <bogus+      16>: 0x0063f004 0x6802145f 0x0009f7f0 0x25dc3f3b
0x000000000063efe8 <bogus+      32>: 0x0009f760 0x00000020 0x0000003b 0x0009f7e0
0x000000000063eff8 <bogus+      48>: 0x000a5ef8 0x0009f760 0x0009f6e0 0x0063f05c
0x000000000063f008 <bogus+      64>: 0x6802192d 0x0009f660 0x0009f7e0 0x000a5ef8
0x000000000063f018 <bogus+      80>: 0x000a4f04 0x000a500c 0x00000021 0x00000020
0x000000000063f028 <bogus+      96>: 0x0009f660 0x0009f6e0 0x0009f760 0x0009f7e0
0x000000000063f038 <bogus+     112>: 0x00000010 0x00000006 0x00000000 0x000001c5
0x000000000063f048 <bogus+     128>: 0x000001c5 0x00000020 0x000a5ff8 0x00000080
... ...

<bochs:12> sreg
es:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1
 Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
cs:0x001b, dh=0x00cffb00, dl=0x0000ffff, valid=1
 Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Accessed, 32-bit
ss:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=7
 Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ds:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=7
 Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
fs:0x003b, dh=0x7f40f3fd, dl=0xe0000fff, valid=1
 Data segment, base=0x7ffde000, limit=0x00000fff, Read/Write, Accessed
gs:0x0000, dh=0x00001000, dl=0x00000000, valid=0
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=0
tr:0x0028, dh=0x80008b04, dl=0x200020ab, valid=1
gdtr:base=0x000000008003f000, limit=0x3ff
idtr:base=0x000000008003f400, limit=0x7ff

<bochs:26> s
Next at t=2257012356
(0) [0x05488d4a] 001b:0000000068021d4a (unk. ctxt): int3                      ; cc

<bochs:27> s
Next at t=2257012357
(0) [0x0053f6e4] 0008:000000008053f6e4 (unk. ctxt): push 0x00000000           ; 6a00

<bochs:28> r
rax: 0x00000000:3edb3b9d rcx: 0x00000000:13f91977
rdx: 0x00000000:13f91977 rbx: 0x00000000:25dc3f3b
rsp: 0x00000000:f8149dcc rbp: 0x00000000:ffffffe0
rsi: 0x00000000:0009f7e0 rdi: 0x00000000:0009f870
r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
r10: 0x00000000:00000000 r11: 0x00000000:00000000
r12: 0x00000000:00000000 r13: 0x00000000:00000000
r14: 0x00000000:00000000 r15: 0x00000000:00000000
rip: 0x00000000:8053f6e4
eflags 0x00000006: id vip vif ac vm rf nt IOPL=0 of df if tf sf zf af PF cf

<bochs:30> x /100w rsp
[bochs]:
0x00000000f8149dcc <bogus+       0>: 0x68021d4b 0x0000001b 0x00000206 0x0063efc8
0x00000000f8149ddc <bogus+      16>: 0x00000023 0x00000000 0x00000000 0x00000000
0x00000000f8149dec <bogus+      32>: 0x00000000 0x0000027f 0x00000000 0x00000000
0x00000000f8149dfc <bogus+      48>: 0x00000000 0x00000000 0x00000000 0x00001f80
0x00000000f8149e0c <bogus+      64>: 0x0000ffff 0x00000000 0x00000000 0x00000000
0x00000000f8149e1c <bogus+      80>: 0x00000000 0x00000000 0x8a885d04 0x00000048
0x00000000f8149e2c <bogus+      96>: 0x00000000 0x77db612a 0x00000002 0x00006148
0x00000000f8149e3c <bogus+     112>: 0x00000000 0x00000000 0x00000000 0x00006134
... ...

 

在int 3前后的寄存器和栈都存在变化,首先不是同一栈,int 3之前是用户栈,int 3之后,切换到了系统栈。esp的值由0063efc8变为了f8149dcc,由于CONTEXT的切换,寄存器的值都发生了变化。
在int 3的内核栈中 0x68021d4b 0x0000001b 0x00000206 0x0063efc8 0x00000023 五个值是新压入的,分别是:
(1)0x68021d4b 产生异常的EIP的后一条指令
(2)0x0000001b CS
(3)0x00000206 EFLAGS
(4)0x0063efc8 ESP
(5)0x00000023 SS
与文档中描述相同。

 

4、TF标志和中断处理

 

调试器的单步跟踪(比如WinDbg的t命令)一般是通过CPU的TF标志实现的。如果TF标志被置位,那么在每执行一条指令后即产生一个int 1中断。

 

<bochs:3> r
rax: 0x00000000:00a18f6a rcx: 0x00000000:ffdffc70
rdx: 0x00000000:00000000 rbx: 0x00000000:ffdffc70
rsp: 0x00000000:8054ac34 rbp: 0x00000000:8054ac50
rsi: 0x00000000:ffdffc50 rdi: 0x00000000:821e7b68
r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
r10: 0x00000000:00000000 r11: 0x00000000:00000000
r12: 0x00000000:00000000 r13: 0x00000000:00000000
r14: 0x00000000:00000000 r15: 0x00000000:00000000
rip: 0x00000000:f871d162
eflags 0x00000246: id vip vif ac vm rf nt IOPL=0 of df IF tf sf ZF af PF cf

 

eflags的第八位是TF标志位,也就是将eflag and 0x100即可将TF置位

 

<bochs:38> setpmem 0x006d1d35 4 0x00034668
<bochs:39> setpmem 0x006d1d39 2 0x6600
<bochs:40> setpmem 0x006d1d3b 1 0x9d
<bochs:41> u rip rip+20
806d1d35: (                    ): push 0x00000346           ; 6846030000
806d1d3a: (                    ): popf                      ; 669d
806d1d3c: (                    ): mov ebp, esp              ; 8bec
806d1d3e: (                    ): mov dword ptr ss:[esp+68], eax ; 89442444
806d1d42: (                    ): mov dword ptr ss:[esp+64], ecx ; 894c2440
806d1d46: (                    ): mov dword ptr ss:[esp+60], edx ; 8954243c

 

由于bochsdbg不支持设置eflag基础器的值,只能设置通用寄存器的值,这就通过修改代码将eflags置位。

单步运行:


<bochs:43> s
Next at t=36941382598
(0) [0x006d1d3a] 0008:00000000806d1d3a (unk. ctxt): popf                      ; 669d
<bochs:44> s
Next at t=36941382599
(0) [0x006d1d3c] 0008:00000000806d1d3c (unk. ctxt): mov ebp, esp              ; 8bec
<bochs:46> s
Next at t=36941382600
(0) [0x006d1d3e] 0008:00000000806d1d3e (unk. ctxt): mov dword ptr ss:[esp+68], eax ; 89442444


TF置位是成功了的:
<bochs:47> r
rax: 0x00000000:00a18f6a rcx: 0x00000000:ffdffc70
rdx: 0x00000000:00000000 rbx: 0x00000000:ffdffc70
rsp: 0x00000000:8054ac22 rbp: 0x00000000:8054ac22
rsi: 0x00000000:ffdffc50 rdi: 0x00000000:821e7b68
r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
r10: 0x00000000:00000000 r11: 0x00000000:00000000
r12: 0x00000000:00000000 r13: 0x00000000:00000000
r14: 0x00000000:00000000 r15: 0x00000000:00000000
rip: 0x00000000:806d1d3e
eflags 0x00000346: id vip vif ac vm rf nt IOPL=0 of df IF TF sf ZF af PF cf
<bochs:48> s
Next at t=36941382601
(0) [0x0053f314] 0008:000000008053f314 (unk. ctxt): push 0x00000000           ; 6a00

 

已经进入ISR 1
(这里不知为是么置位了TF后单步了两条指令才跳入ISR 1,是bochs的实现原理问题?存疑在此。)

 

<bochs:49> info idt
Interrupt Descriptor Table (base=0x000000008003f400, limit=2047):
IDT[0x00]=32-Bit Interrupt Gate target=0x0008:0x8053f19c, DPL=0
IDT[0x01]=32-Bit Interrupt Gate target=0x0008:0x8053f314, DPL=0
... ...

你可能感兴趣的:(c,windows,虚拟机,XP,table,Descriptor)