关于第一个问题,对于手工触发的蓝屏(停止码为0xE2,包括使用.crash命令的),KeBugCheck2故意判断了下,如果是就不中断了,看下汇编便可看到这个逻辑:
nt!KeBugCheck2+0x3e6:805260d9 817d08e2000000 cmp dword ptr [ebp+8],0E2h ;看第一个参数,即StopCode是否等于E2805260e0 747e je nt!KeBugCheck2+0x46d (80526160) ;如果相等则直接跳到下一个步骤;;如果不等,则打印信息后中断到调试器
*** Fatal System Error: 0x0000008e (0xC0000005,0xFA02F463,0xF9C4BB68,0x00000000)
Break instruction exception - code 80000003 (first chance)
A fatal system error has occurred.Debugger entered on first try; Bugcheck callbacks have not been invoked.
...
;;如果是0xe2,则直接跳到这里
nt!KeBugCheck2+0x46d:80526160 e85199feff call nt!KeDisableInterrupts (8050fab6) ;清除中断标志80526165 b11f mov cl,1Fh80526167 ff1548464d80 call dword ptr [nt!_imp_KfRaiseIrql (804d4648)] ; 提升IRQL8052616d b8ffffffff mov eax,0FFFFFFFFh
问题2,x86 CPU提供了CLI指令来清除(允许)中断标志,KeDisableInterrupts函数正是使用这条指令来做的:
lkd> u nt!KeDisableInterruptsnt!KeDisableInterrupts:80501d58 9c pushfd ; 将标志寄存器压入栈80501d59 58 pop eax ; 弹出到EAX寄存器,这是读取标志寄存器的典型做法80501d5a 2500020000 and eax,200h ; 取IF位,也就是中断标志位80501d5f c1e809 shr eax,9 ; 右移到最低位80501d62 fa cli ; 清除IF位80501d63 c3 ret
前几条指令是取当前的IF位作为返回值。
在这一步之后的操作都是不依赖于中断机制的,所以只能做有限的操作。