最近搞开发一个软件.涉及IDT,发现一些奥秘.拿出分享.
在98下,扩展一个IDT涉及很多问题.我前几天在MS的KERNEL讨论组上POST了一个问题,结果成堆的高手却没有人回答.估计9X下的确很少再有人DIG奥秘了.所以自己反汇编了一下98的代码,有了一小点的发现.
1.OS有一个全局的V86IDT.储存在V86_IDT变量.该变量在我的EWIN98代码上的绝对地址28:c000d464h.该处的IDT乃是在V86模式下IDTR对应的IDT.该IDT的限长为300H,IDT的起始地址为c000d474h.也就是说,起始V86也只提供0-6FH中断.但是实际上中断最终都被转发到了V86_IVT区.也就是所谓的实模式中断向量表去.
2.对于各个VM,OS在VMCB里还有一个地方存储对于VM的IDT.也就是说,当一个VM在执行时,真正加载的IDT是VMCB里指定的IDT.由于OS没有直接引用VMCB,对VMCB的引用则是通过VM句柄来进行的.具体的IDT位置通过如下方法获得:
MOV EBX,[CURRENT_VM_HANDLE]
LIDT FWORD PTR [EBX-36H]
也就是说,VMHANDLE-36H就可以获得当前VM的IDT表.
注:EWIN98SE上测试结果为VMCB-3CH为VM对应的IDT.
现在有些朋友可能糊涂了,V86IDT干吗用呢?起始V86IDT是给VXD用的.一个VXD可以要求设置当前运行环境为V86模式.这时,OS会切换IDT给VXD一个"初始"的V86IDT环境.
通过上述的知识,我当时的问题就可以解决了.当时我用LIDT指令加载IDTR.然而根本就不起作用.因为OS在一个任意的时候就切换了IDT.自己设置的IDT能够维持的时间太有限了.现在,我们可以通过修改VM的IDT表结构来达到目的.也就是在VM_HANDLE-36H处修改IDT限长和IDT起始地址来达到目的.
具体的操作就不展开了.懂的朋友自然懂了,不懂的估计也就更糊涂了.:)
然后讲解一下OS到底是如何服务INT5FH以上的V86中断的.
当一个INT XX指令发出,引发一个GP故障.OS的GP处理程序检查是否INT XX指令.是,将返回地址+2,跳转到DOS中断向量表.执行后返回.否,兰屏.