说的基本对啊,哪里不清楚? 以下面的一项为例来说: 3e: 817789cc atapi!IdePortInterrupt (KINTERRUPT 81778990)
81778990是所谓的中断对象地址,也就是一个KINTERRUPT 结构。 kd> dt _KINTERRUPT 81778990 nt!_KINTERRUPT +0x000 Type : 22 +0x002 Size : 484 +0x004 InterruptListEntry : _LIST_ENTRY [ 0x81778994 - 0x81778994 ] +0x00c ServiceRoutine : 0xf9967fbe unsigned char atapi!IdePortInterrupt+0 +0x010 ServiceContext : 0x8178a030 +0x014 SpinLock : 0 +0x018 TickCount : 0xffffffff +0x01c ActualLock : 0x81778bf4 -> 0 +0x020 DispatchAddress : 0x804ebac7 void nt!KiInterruptDispatch+0 +0x024 Vector : 0x3e +0x028 Irql : 0xd '' +0x029 SynchronizeIrql : 0xd '' +0x02a FloatingSave : 0 '' +0x02b Connected : 0x1 '' +0x02c Number : 0 '' +0x02d ShareVector : 0 '' +0x030 Mode : 1 ( Latched ) +0x034 ServiceCount : 0 +0x038 DispatchCount : 0xffffffff +0x03c DispatchCode : [106] 0x56535554
其中DispatchCode字段的地址: kd> ? 81778990+3C Evaluate expression: -2122872372 = 817789cc 就是登记在IDT表里的中断服务例程(ISR)的地址。上面显示出来的0x56535554其实是ISR代码的前几天指令: kd> u 817789cc 817789cc 54 push esp 817789cd 55 push ebp 817789ce 53 push ebx 817789cf 56 push esi 817789d0 57 push edi 从执行的角度来看,发生中断后,CPU转来执行817789cc处的代码,这段代码做了些预处理后,便将中断对象的地址放到EDI寄存器中,然后跳转到KiInterruptDispatch函数: 81778a4f bf90897781 mov edi,81778990h 81778a54 e96e30d7fe jmp nt!KiInterruptDispatch (804ebac7) 这相当于把中断对象当做参数调用KiInterruptDispatch 函数。KiInterruptDispatch 函数内部再调用中断对象里的服务函数: ServiceRoutine : 0xf9967fbe
从驱动程序注册中断的过程来看,驱动程序先创建一个中断对象,然后把KiInterruptTemplate处复制样板代码过来: kd> dd nt!KiInterruptTemplate l(106/4) 804ebb5e 56535554 54ec8357 4489ec8b 4c894424 804ebb6e 54894024 44f73c24 00007024 850f0002 804ebb7e 00000112 247c8366 2374086c 5024648c 804ebb8e 38245c8c 3424448c 30246c8c 000030bb 804ebb9e 0023b800 8e660000 d88e66e3 64c08e66 804ebbae 00001d8b c7640000 00000005 ffffff00 804ebbbe 245c89ff 00fc814c 0f000100 00009d82 804ebbce 2444c700 00000064 05f6fc00 ffdff050 804ebbde bf0b75ff 00000000 fffcd9e9 45f790ff 804ebbee 02000070 f7097500 00016c45 e3740000 804ebbfe 0fc3210f 210fc921 185d89d7 891c4d89 804ebc0e 210f207d f1210fdb 89ff210f 4d89245d 804ebc1e 0000bb28 7d890000 fb230f2c 203d8b64 804ebc2e 8b000000 0002f89f fc8f8b00 0f000002 804ebc3e 230fc323 009f8bc9 8b000003 0003048f 804ebc4e d3230f00 8bd9230f 0003089f 0c8f8b00 804ebc5e 0f000003 复制过来后,要做一些修改,把中断对象的地址替换进去。 kd> dd 817789cc l(106/4) 817789cc 56535554 54ec8357 4489ec8b 4c894424 817789dc 54894024 44f73c24 00007024 850f0002 817789ec 00000112 247c8366 2374086c 5024648c 817789fc 38245c8c 3424448c 30246c8c 000030bb 81778a0c 0023b800 8e660000 d88e66e3 64c08e66 81778a1c 00001d8b c7640000 00000005 ffffff00 81778a2c 245c89ff 00fc814c 0f000100 00009d82 81778a3c 2444c700 00000064 05f6fc00 ffdff050 81778a4c bf0b75ff 81778990 d7306ee9 45f790fe 81778a5c 02000070 f7097500 00016c45 e3740000 81778a6c 0fc3210f 210fc921 185d89d7 891c4d89 81778a7c 210f207d f1210fdb 89ff210f 4d89245d 81778a8c 0000bb28 7d890000 fb230f2c 203d8b64 81778a9c 8b000000 0002f89f fc8f8b00 0f000002 81778aac 230fc323 009f8bc9 8b000003 0003048f 81778abc d3230f00 8bd9230f 0003089f 0c8f8b00 81778acc 0f000003 红色的DWORD就是更新的内容。更新好这段代码后,再将准备好的这段代码的地址登记到IDT表中。这也就是IoConnectInterrupt函数内部要做的事情
NTSTATUS IoConnectInterrupt( OUT PKINTERRUPT *InterruptObject, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock OPTIONAL, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN KAFFINITY ProcessorEnableMask, IN BOOLEAN FloatingSave );
以下是 驱动程序的典型调用方法:
status = IoConnectInterrupt(&pDevExt->Interrupt, SerialCIsrSw, pDevExt->CIsrSw, NULL, pDevExt->Vector, pDevExt->Irql, pDevExt->Irql, pConfig->InterruptMode, pDevExt->InterruptShareable, pConfig->Affinity, FALSE);
这下明白了些了没?:-)
|