QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

跳转到指定楼层
1#
发表于 2004-10-9 14:29 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
文章内容:
5 N9 D. e- ]2 q3 h, O2 Q+ i8 f! R--------------------------------------------------------------------------------
5 G* k+ ?; o" `作者:suxm < suxm@nsfocus.com >
7 I# v, P/ R! m3 M* f1 l" a8 U主页:http://www.nsfocus.com
9 M8 G, \6 z+ e" ^) s) d日期:2001-08-13% O/ y9 k. j5 P$ M, a
; L9 ], u% A% i) [! r
几乎每一个不太守纪律的Windows developer都想在Windows中挂一个ISR,就象在DOS下那样,接管Windows的中断,然后,做一些离奇 的事情。由于ISR是很特殊的程序(常驻性、触发性、Ring0级),所以有很多很特殊的用途。最基本的用途,应该算是硬件驱动开发了:要 想接管硬件中断,没有ISR是不行的。/ g9 }5 c) `( y. e: ~1 ]- d9 @
迄今为止,在Windows 3.x & 9X下,ISR的编写、调试已经不是秘密了。但是在Winnt/2k下,这还是很痛苦的事情。我听一个国外的哥们 说,他本科毕业论文就是<>, 怎么样,faint了吧?呵呵。
/ Y# _! p# f' C; N3 {. W% Q% n让我们先来回忆一下Win9x下ISR是怎么回事(参见我的文章<>)。
" u) v# V2 m2 z- sWin9x下,IDT中的每一项,也就是每一个描述符,都定义了256个中断中的一个。还记得实模式下MS-DOS环境中的中断向量表吧(就是 那张从内存的0000:0000开始的向量表,每一个表项有4个字节,一共有256个中断向量)?在保护模式下,中断描述表IDT代替了中断向 量表IVT。虽说中断向量表IDT可以容纳8192个中断描述符,可是CPU能利用的只有处于前面的256个。所以中断描述表(IDT)的长度限 制应该是7FFh( ),
# r1 p! |! Y* p1 }8 b0 B" x  p, s5 y. X# K5 C
, R7 t& q$ }% }+ A2 s

+ E% r4 w2 w) R/ D其实中断描述表(IDT)中可以有两种描述符:Interrupt gate描述符、Trap gate描述符(更确切的应该说有三种:Interrupt gate描述 符、Trap gate描述符、Task gate描述符,但是一般来说是不会包含Task gate描述符的)。图1显示了Trap/Interrupt gate描述符的结构。这里 提到了gate这个词,一般译作“门”。如果有人跟你说起“中断门”,千万不要大惊小怪,“中断门”更形像地直意了中断调用的过程: 中断调用就像就经过一扇门一样,这个门就是中断描述符,因为中断描述符中有DPL等权限盘查的标志,所以要想通过这扇门调用相应的 中断服务程序是需要一定的资格的(CPL<=DPL)。3 c$ @3 _- j; Q, n' `. {+ K
Trap和Interrupt gate非常相似,一般来说Trap gate是用来捕获系统异常,而Interrupt gate用来响应中断。在具体的实现上,只有一点不 同:Interrupt gate会将IF置为0,这样可以屏蔽硬件中断。但是Trap gate却不会改变IF的值。  y. k7 M( d: b' ?
下面的代码示意了如何设置一个键盘中断描述符(interrupt 51h):
) \- u9 R! z& I9 Z: kint51 dw kb_int ;keyboard-handler offset
) B. H, a) j" Y( B7 @& ddw kb_sel ;keyboard-handler code selector
5 h1 g) ?6 k  N8 U% W( o* H6 J: pdb 0
. v5 J  ]2 z0 h$ zdb 8eh ;386 interrupt-gate6 @$ U" J8 J) W, k2 w) u; f! u
dw 0 ;offset is in first 64KB of segment  |! a$ ~" h3 o1 q% t$ i* q
是不是有些困惑?为什么键盘中断变成int 51h了?以前在DOS下不是int 9h吗?5 w  x; l3 f" g
这个问题的答案是这样的,由于在保护模式下,有很多中断号分配给了系统异常处理(比如说int 9h分配给了CPU No NPX异常处理), 所以,硬件中断处理的中断号都作了调整:实模式下的中断号08h——0Fh和70h——77h(即硬件中断号IRQ 0~16)对应着保护模式下的中断 号50h——5Fh。
% O, n! Y  q* d1 c提问:Win9x中,是如何区分硬件中断IRQ 12和int 5Ch 调用(NetBIOS调用)的呢?+ ]1 k& d  a  I  b; t/ B- t
答案:由于IDT的50h——5Fh中断描述符的DPL=0,这是专门用来截获int指令的,而硬件中断不管DPL是多少都可以被调用。Win9x就 是通过这点区别来分辨到底是int 5Ch这条指令还是IRQ 12的硬件中断,从而调用系统服务或ISR。; I) s! I% T; d# \1 u1 J
在单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的情况是大不相同 的。8 k3 u8 k  P3 h  w9 E
Aladin BasysGate BIG_WWW Hugo_C STAT_02 STAT_13 OTTO SanderD Notebook! s0 u* I0 @" X' Z
IRQL + g/ Q& s. |7 O: o/ D* G
1 3D 3D
  e* }  e: s& L, A. M# B2 41 41
# E7 \# N- L, s' p) z3
6 C$ p% h" g+ t# i' M$ A4 u4 51 51 51
$ O- x: m. ?$ O1 S5 61 61 61/ J0 y5 W- {9 U" D$ L+ U, ?
6 71 71
+ T* U0 h# Y' a$ U! q7 81/82 81/82 81. A( S# V$ }+ v6 o: s; u; _5 Z9 S
8 91/92 91/92 91/92: v3 `0 o1 b% z( ?  p  Y! D7 j$ ^5 K% t; R
9 A2 A2 A1
2 `" K! G/ h5 w% h7 R10 B1 B1 B1/B2
  j/ i5 M1 e  Q# B8 [8 H/ D* @117 z' Q( w& _) P2 ?1 C
12 3F & }5 f( T! p) |0 \6 U
13 3E 3E 3E 3E
; c7 x. x) A+ b/ a14
( d9 L2 d# L2 H15 3C 3C 3C 3C 3C  F* Q% n1 m$ u: g
16 3B 3B 3B
0 S. F& z, c$ ?: P4 ~. |17 3A 3A$ w, ^; q" j; c4 c, g! g6 N
18 39 390 c0 N5 q5 [. c9 F  E
195 j1 S& W) S6 Y' P
20 37 37 37* u$ ?3 M8 k$ Q6 k& n3 F/ N2 ~* t
21 36 36 36 36 36 36
9 b8 d- A* [# ^5 }( v9 }; z. C# }22 35 35
) [5 P# x) l' p/ B* v" }7 O, x! J1 [4 V23 34 34 34 34 34 34+ D! D+ f. F+ A: ^
24 33
) j+ l( c. F* s( f5 a7 L$ v25 - W# u% Z5 K& T! [! s+ c
26 31 31 31 31 31 31
3 R5 n" K% U" ]3 Z% G$ O! {27 C1 38 C1 38 38 38 38 C1 38' s  ~; o; o% m& D3 i) ?, \
28 D1 30 D1 30 30 30 30 D1 30
2 o2 B( g) F" b( m4 Z1 D7 c29 E1 E1 E1
* B( ?. v. \7 a- q& \% Z4 e30 FE/FD FD/FE FD/FE
. k/ P! G$ V3 F1 B; O" G31 1F/FF 32 1F/FF 32 32 32 32 1F/FF 32
  O* e: Q0 I/ M) z
3 z% b" z3 j1 [0 X255 50 50 50
2 `0 M5 G% V4 ^9 u3 }. EDPL3 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E
- i! H5 ], J" Y' X0 Y
  o. C1 R% Y+ Y$ }* `机器配置:. F1 D! P7 Q2 ]5 [# Y3 x5 `8 f
ALADIN - Dual Pentium II 266 MHz, NT 4.0 (free) SP35 u6 J) k) Y* [$ |  h% [
BasysGate - Pentium II 233 MHz, NT 4.0 (free) SP3
- F" I8 t8 c' U: U3 lBIG_WWW - Dual Pentium II 266 Mhz, NT 4.0 (free) SP3& j9 A0 R6 s' X- o8 u
Hugo_C - AMD K6 200 Mhz, NT 4.0 (checked) SP1) Z& Z. H, X; ?# f9 r& e
Stat_02 - Pentium 166 MHz, NT 4.0 (free) SP3
& H/ c* }! E, uStat_13 - Pentium Pro 200 Mhz, NT 4.0 (free) SP2
& @4 u6 j5 S8 R8 ~$ e5 WOTTO - Pentium II 300 MHz, NT 4.0 (free) SP41 W8 `3 b6 ?! M) y2 T0 p
SanderD - Dual Pentium 166 MHz, NT 4.0 (free), SP38 V& u1 o% @: E1 t5 i
Notebook - Pentium 200 MHz, NT 4.0 (free), SP3
) m% [- r  C2 j2 w
3 _) j9 L7 X) |6 Y在Win2k下,实模式下的中断号08h----9Fh和70h----77h不再对应着保护模式下的中断号50h------5Fh或30h-----3Fh。那么,究竟是怎样一种 映射关系呢,至今还没有公开的答案。我们可以用HalGetInterruptVector(参见Win2k DDK Help)这个函数获得硬件中断对应于Win2k的 中断号(即IDT中的位置)。但是这不是固定映射的关系,也许明天开机的时候,就会得到不同的返回值。' U, y" f" B" g) }- ~& h( T( `) {
Win2k下,在SoftIce中用:idt命令可以看到当前系统的IDT状态。
+ |. y0 D7 l% l5 h0 C:idt0 L  B! i4 k$ o4 d% O! n! z
Int Type Sel:Offset Attributes Symbol/Owner
. W1 |0 A7 @; [- J/ Z) k& t' YIDTbase=80036400 Limit=07FF 从这里我们可以看到IDT的Base Address和Limit
4 y) h( j6 s6 l8 [4 I8 m0000 IntG32 0008:80465946 DPL=0 P ntoskrnl!Kei386EoiHelper+0590
7 R2 @# |) X7 K, _; }" x0001 IntG32 0008:80465A96 DPL=3 P ntoskrnl!Kei386EoiHelper+06E0; w' E8 U  q+ ?0 H; D6 w
……
* s% k; e  i6 ^5 x  f00FD IntG32 0008:804646F2 DPL=0 P ntoskrnl!ExReleaseResourceForThread+092
  @& u1 q1 r5 C00FE IntG32 0008:804646F9 DPL=0 P ntoskrnl!ExReleaseResourceForThread+0928 a5 x; X8 Z9 A, X# t
00FF IntG32 0008:80464700 DPL=0 P ntoskrnl!ExReleaseResourceForThread+093
8 s5 a8 o. g# a从上面的输出我们可以看到在Win2k下,IDT的有效长度还是7FFh,这与前面讲到的Win9x下的IDT的长度是一样的。其实这是由CPU 只能利用IDT的前256项决定的。' }3 c4 ?2 r% f( o0 l: @
在Win2k下,在命令行敲入winmsd.exe,可以看到自己机器上硬件中断号的分布状况。
- q' H4 `" A. f7 w7 w1 N0 c+ r+ R3 H
+ ^* n( s' q. o1 ]/ v! r

3 s$ g0 T* n/ n* K% T提问:IDT表的Base Address怎样得到的呢?
* F3 J1 x7 N" W" t. L. I答案:sidt指令,比如说sidt [eax],就是把IDT 寄存器(其中含有IDT的Base Address)中的值放到[eax]指向的地址。请看一下7 X2 N( [+ ]: Y+ U
http://developer.intel.com/design/intarch/techinfo/Pentium/instform.htm的说明:0 q9 l' `( O' }
SIDT - Store Interrupt Descriptor Table Register0 t" G4 O. t" `& y" \) R' U/ c

, E, o7 R0 ]2 u& F4 nGuido Wischrop提供了下面的代码可以读取IDT的所有256项。
5 \" T& {5 B7 R3 z. p7 z* r6 @9 W4 H! Z: g' {; I, |
UCHAR *mBuffer;4 e9 F+ I0 n( ~# Z
ULONG dummy;
. p! h- y& [9 n2 |……
& l" x: M. M" @7 ]' ~/ d( w_asm- q3 A& d2 I0 q& G9 ?4 W9 [# E$ a
{
: O  `" o3 B& z2 B) v) V4 dmov esi,mBuffer
- E% {, ]7 Z$ _sidt [esi] //load IDTR to *mBuffer
, W* m) G/ b5 e9 e7 @. Rmovzx ecx,word ptr [esi] //load size of IDT to ECX
/ M1 p8 e) p) D6 @  dmov ebx,dword ptr [esi+2] //load Base Address of LDT to EBX3 C  ]" s7 M2 H0 L
inc ecx ) }! G0 D  n$ [4 |+ [: D9 p
mov edi,mBuffer //mBuffer is the target$ Z& A: ^  Z, s; B+ o
mov dummy,ecx //store size in dummy
. o, O4 L: F: _+ l6 X& T7 xmov esi,ebx //store IDT Base Address to ESI$ a! C" G+ |9 f+ a5 E6 Q; \: }
shr ecx,2
1 J: u6 G9 U7 r$ w- r5 prep movsd //copy IDT to mBuffer5 X" a! m  o- k# g
}
( n9 w# b4 E6 W0 ?$ Y; v9 O3 m" ?' A6 I7 [7 S
这样我们就可以得到想要的IDT中的某一项,那么,我们是不是可以通过改写内存的方式直接替换相应的IDT表项呢?答案是肯定 的,有人声称这样能成功。我觉是没有太大的必要,因为通过标准的Kernel API调用也可以实现。
. ]" a4 E& j- B' I* q  D我们可以用Windriver生成代码来简单地体会一下挂硬件中断ISR的感觉。
- F9 Z1 r6 w5 R; V4 j(1) Windriver---> Driver Wizard---->New Project----->ISA CARD1 r, x, H! W' f9 y, U
(2) Interrupts---> New
! R# f1 S/ K$ D7 HInterrupt Number = 14(或别的) & Edge Triggered & Shared( S9 {3 ~% h- _/ s; y2 X( W, F
(3) Listen to Interrupts
  c' q( c! b. C! _如果没有出现错误,则表明这个硬件中断可以挂我们的ISR。# B4 t: j3 M, b  L/ m
(4) Generate Code
) T+ ]- b% u' F, A1 K! `(5) Build and Run
. T: w5 g7 c# t, l! Z3 C, S- p2 m(6) Enable Interrupt
- l7 e$ M! v" q% M; f* G3 m* R3 Z(7) 切换到SoftIce中去(Ctrl + D),然后敲:intobj命令,可以看到如下的输入信息:5 y- }! W4 p& Y  g" k- F! \3 R
:intobj0 p7 ]$ }6 Q6 Q, I8 b3 y
Object Service Service Affinity5 T" R3 `) Q/ b, r7 W' f) p7 b
Address Vector Address Context IRQL Mode Mask Symbol/ S# y* S' S* @, r; }) i& h
FD349508 31 F7861900 FD4683E0 1A Edge 01 i8042prt!.text+1600- n; ^0 P- l$ K, h9 e2 ]% V, |
FD348D88 3C F786798C FD35D020 0F Edge 01 i8042prt!PAGEMOUC+020C
0 \+ F% F- H" t) I$ h6 C# N* L0 C1 gFD189708 3D FC8F22C0 00000001 0E Edge 01 WINDRVR!.text+2040) H; q! p+ \+ ]' ~
FD48F788 3E FD10FE42 FD4BD030 0D Edge 01 atapi!.text+5AE2# _8 Q! o3 r7 R# `9 Q7 g, V5 g
FD34A888 3F FD057AA0 FD34E0DC 0C Level 01 NDIS!PAGENDSM6 s. C7 l: L* E: F2 t, m
NTICE: Exit32 PID=70 MOD=ps2_diag+ V4 ^) V( Q: C/ W2 A! J

( ?9 X( S6 w6 W从上面可以看到,0Eh(即14)号硬件中断被映射到了IDT的3Dh项。还不相信吗?好,让我们来测试一下。在SoftIce中敲入如下的指 令:genint 3d,看到什么了?呵呵,屏幕显示如下:
0 N5 O- h) K, v2 e7 ^. E: i) C: l( U  a0 C# g
1 ^' U+ q& N3 j& V% r8 z
, s3 u# a" [$ Y6 ?/ y' ^8 g
我们用:genint 3d这条指令模拟了一次硬件中断,结果表明我们的ISR确实是挂在了IDT的3Dh项处。在Softice中再运行几次genint 3d试试 看,屏幕上会输出什么样的结果呢?当然是Got Interrupt0 number 2,Got Interrupt0 number 3之类的信息啦。
1 m! ?! W/ T8 ]9 N8 \1 ?! ]
1 m- T! b! N% T8 S# X$ @! h一个问题马上被提出来了
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-4-18 14:19 , Processed in 0.443078 second(s), 52 queries .

回顶部