QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2359|回复: 0
打印 上一主题 下一主题

关于Winnt/2k IDT的一些思考

[复制链接]
字体大小: 正常 放大
韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

跳转到指定楼层
1#
发表于 2004-10-9 14:29 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
文章内容:
; m' _0 ?- K5 _! q  H$ c; ^  p--------------------------------------------------------------------------------; J- F" Y% w- L4 O# G3 t7 q
作者:suxm < suxm@nsfocus.com >: C4 m! J& _5 D+ J1 A
主页:http://www.nsfocus.com8 G$ c. G( d+ M) }
日期:2001-08-13
. i2 m5 l$ J! V* A3 Z: Y: {1 |4 z0 I$ ^% |3 j6 n* B% v
几乎每一个不太守纪律的Windows developer都想在Windows中挂一个ISR,就象在DOS下那样,接管Windows的中断,然后,做一些离奇 的事情。由于ISR是很特殊的程序(常驻性、触发性、Ring0级),所以有很多很特殊的用途。最基本的用途,应该算是硬件驱动开发了:要 想接管硬件中断,没有ISR是不行的。
6 @( W: N* A  H' h0 p迄今为止,在Windows 3.x & 9X下,ISR的编写、调试已经不是秘密了。但是在Winnt/2k下,这还是很痛苦的事情。我听一个国外的哥们 说,他本科毕业论文就是<>, 怎么样,faint了吧?呵呵。: O/ Q! N3 Z; f! x- M
让我们先来回忆一下Win9x下ISR是怎么回事(参见我的文章<>)。& l. P3 M6 p8 B( l! |
Win9x下,IDT中的每一项,也就是每一个描述符,都定义了256个中断中的一个。还记得实模式下MS-DOS环境中的中断向量表吧(就是 那张从内存的0000:0000开始的向量表,每一个表项有4个字节,一共有256个中断向量)?在保护模式下,中断描述表IDT代替了中断向 量表IVT。虽说中断向量表IDT可以容纳8192个中断描述符,可是CPU能利用的只有处于前面的256个。所以中断描述表(IDT)的长度限 制应该是7FFh( ),
! ?" I: e% h! w( I- x' |; e9 v# n6 c& z$ g: E  I6 Q; G

  P8 D  l/ L6 L7 p' K: s4 }9 D9 L$ c& b7 K/ M, n8 k! z1 d1 Q
其实中断描述表(IDT)中可以有两种描述符:Interrupt gate描述符、Trap gate描述符(更确切的应该说有三种:Interrupt gate描述 符、Trap gate描述符、Task gate描述符,但是一般来说是不会包含Task gate描述符的)。图1显示了Trap/Interrupt gate描述符的结构。这里 提到了gate这个词,一般译作“门”。如果有人跟你说起“中断门”,千万不要大惊小怪,“中断门”更形像地直意了中断调用的过程: 中断调用就像就经过一扇门一样,这个门就是中断描述符,因为中断描述符中有DPL等权限盘查的标志,所以要想通过这扇门调用相应的 中断服务程序是需要一定的资格的(CPL<=DPL)。; K: \( {1 ]6 A; y
Trap和Interrupt gate非常相似,一般来说Trap gate是用来捕获系统异常,而Interrupt gate用来响应中断。在具体的实现上,只有一点不 同:Interrupt gate会将IF置为0,这样可以屏蔽硬件中断。但是Trap gate却不会改变IF的值。
$ b1 p/ r! S! [, Q3 i1 R; V下面的代码示意了如何设置一个键盘中断描述符(interrupt 51h):
6 ~/ a* M# t. N  P; pint51 dw kb_int ;keyboard-handler offset
9 n8 E  R1 g3 g/ w7 X( @dw kb_sel ;keyboard-handler code selector
1 V9 W0 C; C7 S6 {/ {) Jdb 0 5 ], d: G8 I  V5 S* a; r
db 8eh ;386 interrupt-gate5 W0 f5 {9 ]- u/ }5 X6 Y
dw 0 ;offset is in first 64KB of segment
& b8 R$ G$ t* Q, I是不是有些困惑?为什么键盘中断变成int 51h了?以前在DOS下不是int 9h吗?& B  q5 o. j% a
这个问题的答案是这样的,由于在保护模式下,有很多中断号分配给了系统异常处理(比如说int 9h分配给了CPU No NPX异常处理), 所以,硬件中断处理的中断号都作了调整:实模式下的中断号08h——0Fh和70h——77h(即硬件中断号IRQ 0~16)对应着保护模式下的中断 号50h——5Fh。. T- j5 _* W6 w) a% A7 U# s4 P( [
提问:Win9x中,是如何区分硬件中断IRQ 12和int 5Ch 调用(NetBIOS调用)的呢?9 ^% `) y1 Z) @+ K
答案:由于IDT的50h——5Fh中断描述符的DPL=0,这是专门用来截获int指令的,而硬件中断不管DPL是多少都可以被调用。Win9x就 是通过这点区别来分辨到底是int 5Ch这条指令还是IRQ 12的硬件中断,从而调用系统服务或ISR。( V. u6 k% b4 p7 G9 J0 q
在单CPU的Winnt下,实模式下的中断号08h——0Fh和70h——77h(即硬件中断号IRQ 0~16)对应着保护模式下的中断号30h——3Fh(看 到有些资料上说Winnt下这个映射关系不是确定的,但是我见过的单CPU的Winnt中基本上都是这样的映射关系,而双CPU的情况下,情况 确实有所不同)。从下面这张统计表(http://www.wischrop-net.de/nt/kapitel7.htm#7_2)可以看到单CPU的情况与双CPU的情况是大不相同 的。
5 O  P) y* j/ ^* ~Aladin BasysGate BIG_WWW Hugo_C STAT_02 STAT_13 OTTO SanderD Notebook* e$ _& l" ^# J% k
IRQL
8 y) Y* G* E* M0 `  h' ~1 3D 3D; B2 `; H! N: V& N0 V
2 41 41" g( }4 A& L( ^
3
3 ]7 a2 ~) H4 h5 P7 ~+ W" O4 51 51 51
9 ]' X4 w& w0 l5 61 61 61
2 j! `' x5 l, J* j) H4 M6 71 71
. J$ {/ a' U: G; Y& @7 81/82 81/82 81; x* I$ R) |( x3 m: I9 s9 S
8 91/92 91/92 91/92
1 C/ _1 A6 i: \2 [0 V) M9 A2 A2 A1
" c8 \% N6 [7 F: u9 e- {10 B1 B1 B1/B2" R1 L0 n8 ?' ^
11' D7 Z: q! L. r0 T2 h
12 3F
& R8 |7 H9 V3 G3 |! Q13 3E 3E 3E 3E1 L! g5 v7 L' Z/ H& _2 b7 e
14
6 h4 Z) e8 B; e% L# Q7 A- B2 D15 3C 3C 3C 3C 3C6 x* p+ J& j: O  \3 S
16 3B 3B 3B$ W2 j5 A0 K8 u+ s* J: Z4 F
17 3A 3A
6 j) q" e* p* n  f; |18 39 39
( f' I# f# o! o  N5 v! L19
1 a5 q  s& O6 t9 K! z( d4 h20 37 37 37" @7 f0 v! O/ F; h+ i4 F
21 36 36 36 36 36 369 J" Z) s; }( G, I. @/ ^; T: ^
22 35 35; R& n5 M- f- X7 B, ~6 R$ i
23 34 34 34 34 34 34
, C9 D* {: }5 `& |8 Q- p" s( U24 33
" l* `! }- C5 y0 F! q5 p  u1 g25 2 J1 x# g0 U9 y7 j! L' j* J3 b
26 31 31 31 31 31 31
6 i% ~/ N0 I$ W( n; t27 C1 38 C1 38 38 38 38 C1 38
+ K' N: ^4 Y- |/ \2 Z5 @28 D1 30 D1 30 30 30 30 D1 30. I7 j" _  w$ w
29 E1 E1 E11 O, P( t0 d' F
30 FE/FD FD/FE FD/FE
' `0 k' ?2 M3 k) z31 1F/FF 32 1F/FF 32 32 32 32 1F/FF 32
$ i/ S- G/ B- J0 A) @7 J+ [- a- v. B: R: E: V% i
255 50 50 50
. a+ v- B1 B9 l' |1 u! ZDPL3 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E3 I  B3 `) t. U

" l2 X' [4 l- v0 P1 E: B机器配置:
3 N* L  j1 S$ ~' r8 q1 AALADIN - Dual Pentium II 266 MHz, NT 4.0 (free) SP37 _# s* ^. w; }
BasysGate - Pentium II 233 MHz, NT 4.0 (free) SP3
6 P" B7 O2 L; b9 F* q! \% WBIG_WWW - Dual Pentium II 266 Mhz, NT 4.0 (free) SP3. z% u1 G! m. w! L9 C) K
Hugo_C - AMD K6 200 Mhz, NT 4.0 (checked) SP13 |7 y2 K" ?8 Y% w, h
Stat_02 - Pentium 166 MHz, NT 4.0 (free) SP35 P( G& A/ @6 F
Stat_13 - Pentium Pro 200 Mhz, NT 4.0 (free) SP2
; s- F, v) c6 ?3 r" w: \3 Y: E! hOTTO - Pentium II 300 MHz, NT 4.0 (free) SP4
' D, n! a& M/ A( ^: q3 bSanderD - Dual Pentium 166 MHz, NT 4.0 (free), SP3
; k& N5 h& a" p+ ?( kNotebook - Pentium 200 MHz, NT 4.0 (free), SP3
- p4 W. @. Y6 I2 q% O& G( M2 a
# [% P* W' e" O! x3 t6 F" g在Win2k下,实模式下的中断号08h----9Fh和70h----77h不再对应着保护模式下的中断号50h------5Fh或30h-----3Fh。那么,究竟是怎样一种 映射关系呢,至今还没有公开的答案。我们可以用HalGetInterruptVector(参见Win2k DDK Help)这个函数获得硬件中断对应于Win2k的 中断号(即IDT中的位置)。但是这不是固定映射的关系,也许明天开机的时候,就会得到不同的返回值。
& P# m" N; R) F; P9 C5 OWin2k下,在SoftIce中用:idt命令可以看到当前系统的IDT状态。
: n5 N$ F  t2 t0 G:idt3 L. Q* O; B9 Y; T* j$ }+ `- J
Int Type Sel:Offset Attributes Symbol/Owner, S- [' l# o- q0 ^2 W( ~
IDTbase=80036400 Limit=07FF 从这里我们可以看到IDT的Base Address和Limit& r2 L3 c: {; O8 U+ f, M
0000 IntG32 0008:80465946 DPL=0 P ntoskrnl!Kei386EoiHelper+0590
1 R, P% H  s3 R0001 IntG32 0008:80465A96 DPL=3 P ntoskrnl!Kei386EoiHelper+06E02 S. l' I. R) n/ i) F
……9 X4 P0 S2 q1 q0 ^
00FD IntG32 0008:804646F2 DPL=0 P ntoskrnl!ExReleaseResourceForThread+092
$ e$ Y6 A2 l; x9 q0 G0 z00FE IntG32 0008:804646F9 DPL=0 P ntoskrnl!ExReleaseResourceForThread+092
2 p2 \) a4 a7 @8 c; Q  O8 `00FF IntG32 0008:80464700 DPL=0 P ntoskrnl!ExReleaseResourceForThread+093/ a* c. ?* ~, w. A4 x) J: o2 ]
从上面的输出我们可以看到在Win2k下,IDT的有效长度还是7FFh,这与前面讲到的Win9x下的IDT的长度是一样的。其实这是由CPU 只能利用IDT的前256项决定的。5 s; }: A# j$ l$ b+ _& b6 S4 S
在Win2k下,在命令行敲入winmsd.exe,可以看到自己机器上硬件中断号的分布状况。
4 e% @( K5 R0 R* g) W* X0 o+ a0 Z- e: P) }. d0 S9 t

/ x5 p$ V- R: g* m
* e) v7 X0 `" u  U1 o! \# [提问:IDT表的Base Address怎样得到的呢?, ]% W' G/ {+ q- g
答案:sidt指令,比如说sidt [eax],就是把IDT 寄存器(其中含有IDT的Base Address)中的值放到[eax]指向的地址。请看一下' v, K$ s. i! l$ |* R
http://developer.intel.com/design/intarch/techinfo/Pentium/instform.htm的说明:
) }0 r. @3 A- p7 o- d$ [SIDT - Store Interrupt Descriptor Table Register/ \1 e# P) s5 \! X
5 r* {4 E7 g/ C% K1 F$ w: ~) k
Guido Wischrop提供了下面的代码可以读取IDT的所有256项。0 p4 T' g9 A; {' z# q

( y3 p1 v# w8 g# z8 kUCHAR *mBuffer;
0 G/ X9 b4 c- a- M7 i# [ULONG dummy;7 T: Q" d1 e0 s# q- l
……7 k* L. O: g# G  D2 e
_asm6 M5 R% l( W8 k7 U+ G
{" D+ d* c) @. V
mov esi,mBuffer & C2 v3 G$ a* l6 g6 \! w% I
sidt [esi] //load IDTR to *mBuffer5 X$ I. |. W2 }9 M" `( h
movzx ecx,word ptr [esi] //load size of IDT to ECX' V9 O/ A0 U( @" j4 T
mov ebx,dword ptr [esi+2] //load Base Address of LDT to EBX  G1 i9 S; q8 h) ?$ f0 z% I
inc ecx
5 D: O) J0 ?: S% J( D+ T6 xmov edi,mBuffer //mBuffer is the target
3 W  d5 X5 k' }+ w" l- u% u: Rmov dummy,ecx //store size in dummy: X5 j( D) t9 ]# V- K: e% E8 ]
mov esi,ebx //store IDT Base Address to ESI
/ \( \4 e" p, T2 I9 E+ ]5 u1 qshr ecx,2 & W" s; j' i0 A
rep movsd //copy IDT to mBuffer
# n. n* \+ S' v1 `}
3 u: w+ ^1 q% V- }9 K" Y: E$ D: d
' ]! j  s8 ~: ?0 J0 z. N$ U这样我们就可以得到想要的IDT中的某一项,那么,我们是不是可以通过改写内存的方式直接替换相应的IDT表项呢?答案是肯定 的,有人声称这样能成功。我觉是没有太大的必要,因为通过标准的Kernel API调用也可以实现。  J6 i5 j3 v; c+ g
我们可以用Windriver生成代码来简单地体会一下挂硬件中断ISR的感觉。
1 {4 M5 A$ ^  W3 T" G(1) Windriver---> Driver Wizard---->New Project----->ISA CARD
8 `( u" ~0 _$ F* z(2) Interrupts---> New2 u# L0 ^  N0 D' H$ D( r
Interrupt Number = 14(或别的) & Edge Triggered & Shared
0 Z  h7 T+ w6 O7 L7 {(3) Listen to Interrupts
7 N/ K) t& t, T5 m如果没有出现错误,则表明这个硬件中断可以挂我们的ISR。, S6 U* [5 X/ s: S2 i! }& Q
(4) Generate Code( W7 g8 M6 Q. z- o
(5) Build and Run
- M# {- ?4 q6 {  ?( k! D(6) Enable Interrupt6 d) ~$ s4 M0 U. z
(7) 切换到SoftIce中去(Ctrl + D),然后敲:intobj命令,可以看到如下的输入信息:# F8 i% N9 f9 t
:intobj
8 m' n  f+ [- H, [/ y: A1 i' e& P" m) LObject Service Service Affinity
2 V+ `4 N  [6 j( s6 A8 KAddress Vector Address Context IRQL Mode Mask Symbol
+ b1 O. ~, Z7 g+ SFD349508 31 F7861900 FD4683E0 1A Edge 01 i8042prt!.text+1600$ P, I) J3 d" L& t; L# Z0 x
FD348D88 3C F786798C FD35D020 0F Edge 01 i8042prt!PAGEMOUC+020C7 g- w- e) i3 t3 \
FD189708 3D FC8F22C0 00000001 0E Edge 01 WINDRVR!.text+2040
9 s" Y! j' E* @FD48F788 3E FD10FE42 FD4BD030 0D Edge 01 atapi!.text+5AE2
8 o" L2 N& b: K5 H" |) P4 ^0 `FD34A888 3F FD057AA0 FD34E0DC 0C Level 01 NDIS!PAGENDSM
( Z6 t2 ~3 O7 o; ~NTICE: Exit32 PID=70 MOD=ps2_diag
5 y% m* c( B% a/ o1 ~  _: N+ t
& n/ s4 h8 u' b' s; N- w& T从上面可以看到,0Eh(即14)号硬件中断被映射到了IDT的3Dh项。还不相信吗?好,让我们来测试一下。在SoftIce中敲入如下的指 令:genint 3d,看到什么了?呵呵,屏幕显示如下:& q+ f) ?1 }# \! `9 D0 S
8 @2 l: g0 K2 C% r& `

! Z* d9 F: w4 a, e9 Y$ g6 r
% Q  i) @' e$ ^8 m" o5 N我们用:genint 3d这条指令模拟了一次硬件中断,结果表明我们的ISR确实是挂在了IDT的3Dh项处。在Softice中再运行几次genint 3d试试 看,屏幕上会输出什么样的结果呢?当然是Got Interrupt0 number 2,Got Interrupt0 number 3之类的信息啦。1 U4 x( x1 b- f" Z
5 ~0 k% n0 A$ n8 U
一个问题马上被提出来了
zan
转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
您需要登录后才可以回帖 登录 | 注册地址

qq
收缩
  • 电话咨询

  • 04714969085
fastpost

关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

手机版|Archiver| |繁體中文 手机客户端  

蒙公网安备 15010502000194号

Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

GMT+8, 2026-6-11 06:50 , Processed in 0.302522 second(s), 51 queries .

回顶部