QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

跳转到指定楼层
1#
发表于 2004-10-9 14:29 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
文章内容:( S: |3 i/ ^3 c) _5 w# l4 o( e
--------------------------------------------------------------------------------
* \( @$ I2 X3 X1 f作者:suxm < suxm@nsfocus.com >5 }8 \* @, |. H
主页:http://www.nsfocus.com& _  v( m8 [- A$ Q' l$ H  a
日期:2001-08-13, S; Y) _4 A4 L

( b: T0 H6 `9 V' k& C几乎每一个不太守纪律的Windows developer都想在Windows中挂一个ISR,就象在DOS下那样,接管Windows的中断,然后,做一些离奇 的事情。由于ISR是很特殊的程序(常驻性、触发性、Ring0级),所以有很多很特殊的用途。最基本的用途,应该算是硬件驱动开发了:要 想接管硬件中断,没有ISR是不行的。5 o# A% s1 _5 E& V, b) ^
迄今为止,在Windows 3.x & 9X下,ISR的编写、调试已经不是秘密了。但是在Winnt/2k下,这还是很痛苦的事情。我听一个国外的哥们 说,他本科毕业论文就是<>, 怎么样,faint了吧?呵呵。
: x2 R" M2 h5 T1 r5 s  K/ {* j/ K让我们先来回忆一下Win9x下ISR是怎么回事(参见我的文章<>)。
3 V2 f" E" Y5 w$ h0 i8 y- UWin9x下,IDT中的每一项,也就是每一个描述符,都定义了256个中断中的一个。还记得实模式下MS-DOS环境中的中断向量表吧(就是 那张从内存的0000:0000开始的向量表,每一个表项有4个字节,一共有256个中断向量)?在保护模式下,中断描述表IDT代替了中断向 量表IVT。虽说中断向量表IDT可以容纳8192个中断描述符,可是CPU能利用的只有处于前面的256个。所以中断描述表(IDT)的长度限 制应该是7FFh( ),
  K! s+ F! p4 ^5 U
2 A' h; h- X0 b/ k6 @9 K0 v: ]0 w+ A8 h" f+ @) l
' z' o( X, F5 {; H, g5 _
其实中断描述表(IDT)中可以有两种描述符:Interrupt gate描述符、Trap gate描述符(更确切的应该说有三种:Interrupt gate描述 符、Trap gate描述符、Task gate描述符,但是一般来说是不会包含Task gate描述符的)。图1显示了Trap/Interrupt gate描述符的结构。这里 提到了gate这个词,一般译作“门”。如果有人跟你说起“中断门”,千万不要大惊小怪,“中断门”更形像地直意了中断调用的过程: 中断调用就像就经过一扇门一样,这个门就是中断描述符,因为中断描述符中有DPL等权限盘查的标志,所以要想通过这扇门调用相应的 中断服务程序是需要一定的资格的(CPL<=DPL)。
9 y. {4 U9 K& N) ]Trap和Interrupt gate非常相似,一般来说Trap gate是用来捕获系统异常,而Interrupt gate用来响应中断。在具体的实现上,只有一点不 同:Interrupt gate会将IF置为0,这样可以屏蔽硬件中断。但是Trap gate却不会改变IF的值。
1 ]& `" G8 ~2 F下面的代码示意了如何设置一个键盘中断描述符(interrupt 51h):& p5 E7 P! v! S& w- O4 x5 ]3 y9 E
int51 dw kb_int ;keyboard-handler offset+ g5 C* r3 Q9 z8 k# r
dw kb_sel ;keyboard-handler code selector; Z: V4 f/ b, e# x
db 0
) i' P( w3 T( e  ?& S3 ?( {) xdb 8eh ;386 interrupt-gate
7 K5 [& n4 @! W. b4 U& Qdw 0 ;offset is in first 64KB of segment6 Q  w" O8 L% D. E+ f% y
是不是有些困惑?为什么键盘中断变成int 51h了?以前在DOS下不是int 9h吗?$ P, {( @% `) @* w- x% D$ w% \
这个问题的答案是这样的,由于在保护模式下,有很多中断号分配给了系统异常处理(比如说int 9h分配给了CPU No NPX异常处理), 所以,硬件中断处理的中断号都作了调整:实模式下的中断号08h——0Fh和70h——77h(即硬件中断号IRQ 0~16)对应着保护模式下的中断 号50h——5Fh。
# A1 H) A+ v. ?# s2 F+ a提问:Win9x中,是如何区分硬件中断IRQ 12和int 5Ch 调用(NetBIOS调用)的呢?
  m' @1 e  D) p$ Q答案:由于IDT的50h——5Fh中断描述符的DPL=0,这是专门用来截获int指令的,而硬件中断不管DPL是多少都可以被调用。Win9x就 是通过这点区别来分辨到底是int 5Ch这条指令还是IRQ 12的硬件中断,从而调用系统服务或ISR。- W. G9 a- e# u2 h9 n
在单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的情况是大不相同 的。) O' b7 L5 ^5 _1 Y% R% j9 N
Aladin BasysGate BIG_WWW Hugo_C STAT_02 STAT_13 OTTO SanderD Notebook5 ?7 V: H+ V! w1 M7 d4 h
IRQL * S) e- b7 b, f! d" }
1 3D 3D; A7 Y; n& \9 \4 |
2 41 412 R5 R$ h# P4 }
3! V0 I: E; h7 ^" x1 j1 {. x  c
4 51 51 51* v% A2 Y6 [) }' ~0 p4 ~7 @+ G
5 61 61 614 h* F7 `0 Q6 C' v, e& V' N
6 71 71
8 G7 |( w/ W7 w8 S1 |, V1 T7 81/82 81/82 81
+ _6 `& Q: W1 u. M7 h0 ~8 91/92 91/92 91/92" l  H4 {6 z8 w  g1 w2 i
9 A2 A2 A1
" K" Q0 @" K1 z10 B1 B1 B1/B2
7 n% B+ G1 q" @) V) e5 }11
, L7 w! o0 ^$ Q# s12 3F   P# Z- |2 J" T+ x+ \& Z* R" ?
13 3E 3E 3E 3E
$ J# ]. _+ Z/ l144 C5 ]. y! n# D
15 3C 3C 3C 3C 3C9 R3 Q5 |7 V7 P/ h; K; ^
16 3B 3B 3B
4 |, ?/ q6 ^- n+ X17 3A 3A" K: C9 `- ~" \* |) T. ^0 P
18 39 39* F; u/ V- Z5 J: e3 P5 n( G
19% n5 i, `( n/ y/ }. A
20 37 37 378 v, r$ j" r( M" a  |1 ?2 q
21 36 36 36 36 36 36& X* G- L4 R6 ], A' t
22 35 35
; G' k/ V6 J% W7 e( d4 w$ L  |23 34 34 34 34 34 34) R' ?/ V: D. i! K4 b; n; C
24 33
) H+ Z1 e0 k4 o25 ! I6 N: f6 o( S" [7 C
26 31 31 31 31 31 31
0 D1 \4 q  T5 @3 C) n9 @4 K27 C1 38 C1 38 38 38 38 C1 38
- e7 x  h+ r: O0 f$ n28 D1 30 D1 30 30 30 30 D1 30
4 F: x! Z7 v+ y" ]! B6 t, o9 h29 E1 E1 E19 \0 Q% z( v  Q- j
30 FE/FD FD/FE FD/FE
( C0 K6 J( p* W' f. y31 1F/FF 32 1F/FF 32 32 32 32 1F/FF 321 t4 a2 h& {: r4 k: L0 }. P- X
7 C! m' `% ]- N* h: H& \5 e; u$ Q. P
255 50 50 50& I3 u# t+ C% Q4 v7 Z$ B# N2 {
DPL3 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E
4 L1 _4 k6 ?+ M0 f5 ~8 \0 o9 k" S  H6 G1 K
机器配置:
9 z6 z; ^3 Y* F& E- ~ALADIN - Dual Pentium II 266 MHz, NT 4.0 (free) SP3+ j; n! X% F: u" K# b1 ~
BasysGate - Pentium II 233 MHz, NT 4.0 (free) SP3
% Y6 u. K9 e+ o' pBIG_WWW - Dual Pentium II 266 Mhz, NT 4.0 (free) SP3* _* J! k8 Y( R! I$ ^
Hugo_C - AMD K6 200 Mhz, NT 4.0 (checked) SP1
& F1 I/ g+ Y8 a8 D& f( a% v2 nStat_02 - Pentium 166 MHz, NT 4.0 (free) SP3( q9 |2 y. G+ G+ K( }$ ]# }8 {
Stat_13 - Pentium Pro 200 Mhz, NT 4.0 (free) SP27 d6 M' b8 ~$ V4 Q' q( e
OTTO - Pentium II 300 MHz, NT 4.0 (free) SP4
: T& D% Z2 M' ~  O' ^4 r+ p+ VSanderD - Dual Pentium 166 MHz, NT 4.0 (free), SP3: o1 F8 Y; U1 b1 j- m
Notebook - Pentium 200 MHz, NT 4.0 (free), SP3
7 C$ N% \7 ?3 f1 m0 k2 n3 _7 G0 {0 U1 y
) M9 c- s- q8 G8 y0 m; D在Win2k下,实模式下的中断号08h----9Fh和70h----77h不再对应着保护模式下的中断号50h------5Fh或30h-----3Fh。那么,究竟是怎样一种 映射关系呢,至今还没有公开的答案。我们可以用HalGetInterruptVector(参见Win2k DDK Help)这个函数获得硬件中断对应于Win2k的 中断号(即IDT中的位置)。但是这不是固定映射的关系,也许明天开机的时候,就会得到不同的返回值。
8 r1 V& O6 F1 I1 V3 Z8 \Win2k下,在SoftIce中用:idt命令可以看到当前系统的IDT状态。
2 v( [+ R* F. j6 ^: e2 _:idt
( D+ \# S8 n: QInt Type Sel:Offset Attributes Symbol/Owner
& r. T7 k1 J+ r! k7 {% TIDTbase=80036400 Limit=07FF 从这里我们可以看到IDT的Base Address和Limit  ]5 @5 Q+ ]3 w: r+ Y
0000 IntG32 0008:80465946 DPL=0 P ntoskrnl!Kei386EoiHelper+0590
2 q" _) J# j2 s8 l, g) E1 T/ z0001 IntG32 0008:80465A96 DPL=3 P ntoskrnl!Kei386EoiHelper+06E0
% D+ T& Y* X" g/ Y% w- G& z……  b1 `! F  s" `- \9 l  {
00FD IntG32 0008:804646F2 DPL=0 P ntoskrnl!ExReleaseResourceForThread+092
# V- l8 u5 Y1 q00FE IntG32 0008:804646F9 DPL=0 P ntoskrnl!ExReleaseResourceForThread+092
/ }+ m' Y% m& c( M9 m7 w7 j( P00FF IntG32 0008:80464700 DPL=0 P ntoskrnl!ExReleaseResourceForThread+093
" O+ M* j6 @' A: ~0 k从上面的输出我们可以看到在Win2k下,IDT的有效长度还是7FFh,这与前面讲到的Win9x下的IDT的长度是一样的。其实这是由CPU 只能利用IDT的前256项决定的。1 \# B$ g4 z  J" N+ l# p' }  h* Q4 i
在Win2k下,在命令行敲入winmsd.exe,可以看到自己机器上硬件中断号的分布状况。
2 ]) g2 O. S+ z$ `) O
" c' G: x& U6 ]2 e$ @) |% b: Z  k& _" Z1 {5 j" W% H

2 r" k7 u( t; V) u4 Q. T5 p提问:IDT表的Base Address怎样得到的呢?
/ S7 G! z6 v) T8 S4 ]2 N答案:sidt指令,比如说sidt [eax],就是把IDT 寄存器(其中含有IDT的Base Address)中的值放到[eax]指向的地址。请看一下
* f$ o0 z6 M& ?% Rhttp://developer.intel.com/design/intarch/techinfo/Pentium/instform.htm的说明:
9 h1 p. {+ ]) A* v, pSIDT - Store Interrupt Descriptor Table Register
, H5 S! f% o. u7 ^; f$ t0 C/ T- H9 L
Guido Wischrop提供了下面的代码可以读取IDT的所有256项。* x3 `5 b+ y' h5 y; c
6 W4 q9 I3 k4 W  Y+ y4 m0 Y; f1 I, S
UCHAR *mBuffer;
3 z! f4 ]6 P3 g8 QULONG dummy;
2 z) k! @: C& \$ }: p+ R……
5 q' R# v1 H! O_asm4 @% a! F6 T5 i- B+ y5 m" _1 J2 H
{
7 i$ J! @1 F) v# d. i+ Y  Tmov esi,mBuffer
# r' ^# _" A/ Psidt [esi] //load IDTR to *mBuffer1 r( Z7 ^' B- r/ j+ n% ^
movzx ecx,word ptr [esi] //load size of IDT to ECX
! x) ~4 @6 @/ w% q8 |' J7 qmov ebx,dword ptr [esi+2] //load Base Address of LDT to EBX1 Z( N3 O: M# }7 c& @' r
inc ecx
8 v. _; G; i+ D8 l) E" Zmov edi,mBuffer //mBuffer is the target
$ |9 @) ]" B) K& q- q8 q) Cmov dummy,ecx //store size in dummy" S0 n. h! {( a
mov esi,ebx //store IDT Base Address to ESI
6 t1 O; K7 Q& H2 J& B) Sshr ecx,2 4 M# a* K0 m) D* H
rep movsd //copy IDT to mBuffer
' f9 l8 K- V" S% [}5 A1 \* k/ O! C4 s4 y6 I
8 Q% Z9 Z8 D& w5 D
这样我们就可以得到想要的IDT中的某一项,那么,我们是不是可以通过改写内存的方式直接替换相应的IDT表项呢?答案是肯定 的,有人声称这样能成功。我觉是没有太大的必要,因为通过标准的Kernel API调用也可以实现。8 P# D1 E) |" l5 i. p
我们可以用Windriver生成代码来简单地体会一下挂硬件中断ISR的感觉。
, u- `" l2 m, m: @(1) Windriver---> Driver Wizard---->New Project----->ISA CARD! I$ d! k& |9 J2 [
(2) Interrupts---> New! z" o# l  \6 s0 ?3 _  B0 \
Interrupt Number = 14(或别的) & Edge Triggered & Shared+ S- Z, q6 N1 {  p& s
(3) Listen to Interrupts
0 Y: h) C" G5 @# C3 i7 b2 u, K# m如果没有出现错误,则表明这个硬件中断可以挂我们的ISR。
+ V: }& ?8 w; E$ o* b- d(4) Generate Code' d- }0 E6 ?8 Y8 w' Z* ?: A
(5) Build and Run
. Z; y4 ]2 c2 N. t  U7 r/ ]7 q(6) Enable Interrupt
3 j! X5 j7 X4 R* s& m1 _(7) 切换到SoftIce中去(Ctrl + D),然后敲:intobj命令,可以看到如下的输入信息:
$ \4 |1 }+ y3 I4 F6 S# T:intobj
. _2 Q: F$ u) L, G) \3 r. ^" F0 Q' f" LObject Service Service Affinity# p  d- ?1 S2 s9 F/ n( c9 h5 q
Address Vector Address Context IRQL Mode Mask Symbol! `% C% q" n3 _) }
FD349508 31 F7861900 FD4683E0 1A Edge 01 i8042prt!.text+16009 q. |5 Z. T" X5 f7 m) l5 q- D
FD348D88 3C F786798C FD35D020 0F Edge 01 i8042prt!PAGEMOUC+020C1 R6 G5 G8 f( W; B/ {/ A
FD189708 3D FC8F22C0 00000001 0E Edge 01 WINDRVR!.text+2040" U. t: I9 \: N1 a5 ~
FD48F788 3E FD10FE42 FD4BD030 0D Edge 01 atapi!.text+5AE2
7 h; p# h' |" c; P  S, {! I" Y! aFD34A888 3F FD057AA0 FD34E0DC 0C Level 01 NDIS!PAGENDSM% @: V4 y, ~$ a  c
NTICE: Exit32 PID=70 MOD=ps2_diag; k) h: B  |7 I
8 P5 d" V3 y0 h$ g2 f
从上面可以看到,0Eh(即14)号硬件中断被映射到了IDT的3Dh项。还不相信吗?好,让我们来测试一下。在SoftIce中敲入如下的指 令:genint 3d,看到什么了?呵呵,屏幕显示如下:
$ d6 y" ]' a' O5 V* b6 z& F% p( S% y) ]

$ [' P' w  K2 u& b$ m2 K' V
7 z) m3 _4 N6 L# B我们用:genint 3d这条指令模拟了一次硬件中断,结果表明我们的ISR确实是挂在了IDT的3Dh项处。在Softice中再运行几次genint 3d试试 看,屏幕上会输出什么样的结果呢?当然是Got Interrupt0 number 2,Got Interrupt0 number 3之类的信息啦。! n; V  `0 h% l
' H% F: f; `  V5 O, j& 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-19 06:07 , Processed in 0.412071 second(s), 52 queries .

回顶部