QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

跳转到指定楼层
1#
发表于 2004-10-9 14:29 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
文章内容:9 h8 i/ r! D7 g4 m: F" o$ _% u
--------------------------------------------------------------------------------
2 R5 T$ {0 @  F- M作者:suxm < suxm@nsfocus.com >3 k. K$ ~' p  e% ]
主页:http://www.nsfocus.com! ?$ Q2 C  x( N4 e/ _% q* D
日期:2001-08-133 t6 J5 u- u0 q9 `8 e

3 t; b0 {4 ~8 V; t: x# {# f几乎每一个不太守纪律的Windows developer都想在Windows中挂一个ISR,就象在DOS下那样,接管Windows的中断,然后,做一些离奇 的事情。由于ISR是很特殊的程序(常驻性、触发性、Ring0级),所以有很多很特殊的用途。最基本的用途,应该算是硬件驱动开发了:要 想接管硬件中断,没有ISR是不行的。. S3 Q) k# F& b# [$ w
迄今为止,在Windows 3.x & 9X下,ISR的编写、调试已经不是秘密了。但是在Winnt/2k下,这还是很痛苦的事情。我听一个国外的哥们 说,他本科毕业论文就是<>, 怎么样,faint了吧?呵呵。
6 L1 v1 N# _9 P7 A/ Y0 a% l让我们先来回忆一下Win9x下ISR是怎么回事(参见我的文章<>)。$ h+ r4 b! T- `6 z2 e, v& M/ R. e
Win9x下,IDT中的每一项,也就是每一个描述符,都定义了256个中断中的一个。还记得实模式下MS-DOS环境中的中断向量表吧(就是 那张从内存的0000:0000开始的向量表,每一个表项有4个字节,一共有256个中断向量)?在保护模式下,中断描述表IDT代替了中断向 量表IVT。虽说中断向量表IDT可以容纳8192个中断描述符,可是CPU能利用的只有处于前面的256个。所以中断描述表(IDT)的长度限 制应该是7FFh( ),
2 t" P9 j  c# e. }. q8 n# V
/ k. O; F  h: F; t
' k0 x' l( q% @# x
% U. R$ D& x0 R% B- Y其实中断描述表(IDT)中可以有两种描述符:Interrupt gate描述符、Trap gate描述符(更确切的应该说有三种:Interrupt gate描述 符、Trap gate描述符、Task gate描述符,但是一般来说是不会包含Task gate描述符的)。图1显示了Trap/Interrupt gate描述符的结构。这里 提到了gate这个词,一般译作“门”。如果有人跟你说起“中断门”,千万不要大惊小怪,“中断门”更形像地直意了中断调用的过程: 中断调用就像就经过一扇门一样,这个门就是中断描述符,因为中断描述符中有DPL等权限盘查的标志,所以要想通过这扇门调用相应的 中断服务程序是需要一定的资格的(CPL<=DPL)。
9 ~- [4 F8 m# z/ I4 `Trap和Interrupt gate非常相似,一般来说Trap gate是用来捕获系统异常,而Interrupt gate用来响应中断。在具体的实现上,只有一点不 同:Interrupt gate会将IF置为0,这样可以屏蔽硬件中断。但是Trap gate却不会改变IF的值。% T2 g% d2 c" f' v8 b/ @- h5 v3 ?
下面的代码示意了如何设置一个键盘中断描述符(interrupt 51h):
' m3 _1 c- Y9 A6 Oint51 dw kb_int ;keyboard-handler offset) M4 K, ^6 ?6 K7 D0 ?7 l
dw kb_sel ;keyboard-handler code selector
' R! N. Q" [' `+ _' L# bdb 0 8 E# C) m, ?1 C; Q  x5 s/ ^. Z) B
db 8eh ;386 interrupt-gate
: U- z& W, w" K; I# s' z0 o7 {dw 0 ;offset is in first 64KB of segment% w' `- R8 f# `: o. g2 V2 X
是不是有些困惑?为什么键盘中断变成int 51h了?以前在DOS下不是int 9h吗?
  c: w6 i' {9 D7 i5 B( O这个问题的答案是这样的,由于在保护模式下,有很多中断号分配给了系统异常处理(比如说int 9h分配给了CPU No NPX异常处理), 所以,硬件中断处理的中断号都作了调整:实模式下的中断号08h——0Fh和70h——77h(即硬件中断号IRQ 0~16)对应着保护模式下的中断 号50h——5Fh。7 h+ J( j) n4 e" v3 N: ?
提问:Win9x中,是如何区分硬件中断IRQ 12和int 5Ch 调用(NetBIOS调用)的呢?( R0 f9 h1 b1 y. X
答案:由于IDT的50h——5Fh中断描述符的DPL=0,这是专门用来截获int指令的,而硬件中断不管DPL是多少都可以被调用。Win9x就 是通过这点区别来分辨到底是int 5Ch这条指令还是IRQ 12的硬件中断,从而调用系统服务或ISR。
1 O8 t& Y- {( r在单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的情况是大不相同 的。- h( U4 B+ Y) X( K8 S7 F
Aladin BasysGate BIG_WWW Hugo_C STAT_02 STAT_13 OTTO SanderD Notebook5 R6 C& y4 q1 F7 `
IRQL
$ M5 _/ y% o( M" @" B1 3D 3D
4 i$ J: ]) P% O* S4 H& c- m$ z& |6 b2 41 41  h1 ~5 ~% w/ k' `* d6 n( l
33 n  t+ f/ L. b- Y" P( [& s" f9 v
4 51 51 518 F9 r# p1 e  Q' f2 U  k
5 61 61 61
- B5 e9 ^) A2 {& X% v7 s# v6 71 71
- d) Y; b8 G' @5 r, N) S7 81/82 81/82 81
7 t' w5 }6 Y" p  K1 r; p8 v8 91/92 91/92 91/92/ C- i; @! u2 I4 o2 R* B
9 A2 A2 A17 A, |. Z7 L9 m* c& l0 l
10 B1 B1 B1/B2- ~* M% w3 R3 \: O+ p+ H+ |
11' J& Q  u# C8 j9 o; ]7 A" u
12 3F 4 I/ d7 }. ^" u) A/ _/ x, M) R
13 3E 3E 3E 3E) E. p. M6 H3 k; I# W  W7 d+ X% }
14  p  L7 \$ R5 C& h9 a
15 3C 3C 3C 3C 3C
8 D' I/ ^: m  R" _  d1 [16 3B 3B 3B
8 U' M; `: R8 u, q9 i$ u' a17 3A 3A  n# H0 y6 G- |
18 39 39
/ P1 c9 G, J4 J# b+ `( B) {198 a7 j8 n0 R% ^
20 37 37 37
) u6 m5 x: N( [2 R* X21 36 36 36 36 36 36
& e5 D: U0 y) Z. l22 35 350 E3 B/ F1 x- `
23 34 34 34 34 34 34
$ e9 j2 w3 P  n0 [# h" s& D% X24 33/ t: ]4 h7 B8 ]& f, s( _
25 3 f8 k" u9 V/ L1 p2 q
26 31 31 31 31 31 31
) a: A" h; B. `* y/ P3 M- t27 C1 38 C1 38 38 38 38 C1 38
' @  z- G6 d6 s% v0 G* c# C28 D1 30 D1 30 30 30 30 D1 30
7 S" W; ]1 Z5 V5 V. s29 E1 E1 E1
2 X# e; a4 z$ Y- r+ Q* g3 X30 FE/FD FD/FE FD/FE
. @1 B. y7 c" a" F. ?' ?+ J, _31 1F/FF 32 1F/FF 32 32 32 32 1F/FF 32
9 Q% }. V6 L2 `% H& |) f
) x$ a* f) A# t8 |255 50 50 50
* e) u8 g( d  g" T& mDPL3 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E 2A-2E3 M( U% X; q( X8 S
  j6 o2 ?& C% Y/ v" q
机器配置:
& e8 ^4 q* Y; {ALADIN - Dual Pentium II 266 MHz, NT 4.0 (free) SP37 {/ y9 Z. r) |1 M+ X8 x
BasysGate - Pentium II 233 MHz, NT 4.0 (free) SP3
8 Q; n( S! d) S5 {9 w( A$ B+ D0 [8 mBIG_WWW - Dual Pentium II 266 Mhz, NT 4.0 (free) SP3
* A& Q8 v! R0 i! T3 WHugo_C - AMD K6 200 Mhz, NT 4.0 (checked) SP1' S. D+ l) F: Y+ l1 I
Stat_02 - Pentium 166 MHz, NT 4.0 (free) SP3+ s4 ~1 r( k  G
Stat_13 - Pentium Pro 200 Mhz, NT 4.0 (free) SP2/ a" y/ K- {8 i) d/ u
OTTO - Pentium II 300 MHz, NT 4.0 (free) SP47 @, Q* b2 [; ]# C+ D8 b
SanderD - Dual Pentium 166 MHz, NT 4.0 (free), SP3
' W5 m* O; ]+ h8 }, r. d( E1 MNotebook - Pentium 200 MHz, NT 4.0 (free), SP3
- p! n3 {# [) m1 ?; z/ F: b2 M/ W
在Win2k下,实模式下的中断号08h----9Fh和70h----77h不再对应着保护模式下的中断号50h------5Fh或30h-----3Fh。那么,究竟是怎样一种 映射关系呢,至今还没有公开的答案。我们可以用HalGetInterruptVector(参见Win2k DDK Help)这个函数获得硬件中断对应于Win2k的 中断号(即IDT中的位置)。但是这不是固定映射的关系,也许明天开机的时候,就会得到不同的返回值。
: ], C& t  o* f, X2 a+ ^. r; OWin2k下,在SoftIce中用:idt命令可以看到当前系统的IDT状态。
3 t6 @& c4 @# v, ?( |:idt
% p. |2 v9 `2 F, yInt Type Sel:Offset Attributes Symbol/Owner) b6 j, q( }4 x# j; D
IDTbase=80036400 Limit=07FF 从这里我们可以看到IDT的Base Address和Limit. ^! m* C  r' s4 x2 Z- H
0000 IntG32 0008:80465946 DPL=0 P ntoskrnl!Kei386EoiHelper+0590: S8 Y: c6 j. o3 O; f; \
0001 IntG32 0008:80465A96 DPL=3 P ntoskrnl!Kei386EoiHelper+06E0
) R" _+ z- x; N* s1 I! k; \0 a+ }……  s6 }% L: p. _9 c7 f$ m0 g
00FD IntG32 0008:804646F2 DPL=0 P ntoskrnl!ExReleaseResourceForThread+0928 h8 N! u2 E3 x- \! e; q
00FE IntG32 0008:804646F9 DPL=0 P ntoskrnl!ExReleaseResourceForThread+092  z1 K9 n  ~4 E+ \4 Z8 B; }; g
00FF IntG32 0008:80464700 DPL=0 P ntoskrnl!ExReleaseResourceForThread+093
8 p4 N) N3 \/ t# }. U6 b从上面的输出我们可以看到在Win2k下,IDT的有效长度还是7FFh,这与前面讲到的Win9x下的IDT的长度是一样的。其实这是由CPU 只能利用IDT的前256项决定的。; r' |: ^/ z' V2 o+ c* m
在Win2k下,在命令行敲入winmsd.exe,可以看到自己机器上硬件中断号的分布状况。
7 ]. {' a8 p0 y: |
* x* R8 n' O7 P$ o2 Q0 T" T6 F, D! p) u5 F& R
0 T$ s; J  b4 s# H  u$ G& v
提问:IDT表的Base Address怎样得到的呢?( L2 b; I( S% q, I/ U
答案:sidt指令,比如说sidt [eax],就是把IDT 寄存器(其中含有IDT的Base Address)中的值放到[eax]指向的地址。请看一下; T( f# C& Q' y/ J3 ^6 T3 p6 d
http://developer.intel.com/design/intarch/techinfo/Pentium/instform.htm的说明:& t. Z4 Y+ `) M
SIDT - Store Interrupt Descriptor Table Register: T* i2 \. X4 U' W
: K9 Q5 G8 n" Z. K6 ~7 f( k: n# `
Guido Wischrop提供了下面的代码可以读取IDT的所有256项。
7 x, l  o5 k* O$ t
' n! \' o- u( O+ zUCHAR *mBuffer;
; G3 B0 h( e4 d0 |- \+ rULONG dummy;2 P* {5 `( }% c& R' C3 V) B' C6 q
……1 `8 K, T" h# N) F7 q" U$ _
_asm7 U- x% r& I9 L" s' w( Q
{
9 k& U* E3 O3 B" Cmov esi,mBuffer
: ?/ T2 }' V% a; Hsidt [esi] //load IDTR to *mBuffer
0 A8 g# ?" Z% i; C. pmovzx ecx,word ptr [esi] //load size of IDT to ECX9 M) j/ n3 j' }
mov ebx,dword ptr [esi+2] //load Base Address of LDT to EBX8 n; W. }7 Q" B8 X
inc ecx 8 H% f4 P' L9 E3 {
mov edi,mBuffer //mBuffer is the target
: D; |; K1 X" Tmov dummy,ecx //store size in dummy. Z9 c0 _! ^; E3 g+ P( t1 w9 Z! x5 W
mov esi,ebx //store IDT Base Address to ESI
6 k4 T) z. |1 N0 ?  Eshr ecx,2 / h# y  i9 }# y; i- q: h+ J
rep movsd //copy IDT to mBuffer
$ p$ V$ J2 A( C0 R) |! n: G}+ E0 x2 B- E6 w% C- h7 r
4 m( R' a9 x+ Y) B4 x" }# e
这样我们就可以得到想要的IDT中的某一项,那么,我们是不是可以通过改写内存的方式直接替换相应的IDT表项呢?答案是肯定 的,有人声称这样能成功。我觉是没有太大的必要,因为通过标准的Kernel API调用也可以实现。
# t7 m- k) R7 R* c, V9 |8 T我们可以用Windriver生成代码来简单地体会一下挂硬件中断ISR的感觉。- f+ V$ }" x. o( v4 R' A
(1) Windriver---> Driver Wizard---->New Project----->ISA CARD
) |3 d3 X. U3 b: T1 H; b(2) Interrupts---> New9 }, O7 {( Q3 A% ?& H
Interrupt Number = 14(或别的) & Edge Triggered & Shared
( N( z! u7 t! C$ A$ g" C1 z: d/ C(3) Listen to Interrupts
8 d. M' @7 j/ m& C9 ]8 t如果没有出现错误,则表明这个硬件中断可以挂我们的ISR。
2 d8 L1 T6 U( h(4) Generate Code
3 J' s. f: A9 _; X; [(5) Build and Run
: G5 Q/ Q+ J" }8 }9 \(6) Enable Interrupt- |) F! |5 M. C% s7 h6 V
(7) 切换到SoftIce中去(Ctrl + D),然后敲:intobj命令,可以看到如下的输入信息:) s2 y$ k1 f( P; X& ^8 n
:intobj. w& T. T/ i) U/ X. n1 T+ }1 k
Object Service Service Affinity
! R. b& `: `! O' x6 G" \, AAddress Vector Address Context IRQL Mode Mask Symbol; t8 Z: E/ r. G- S9 V0 S
FD349508 31 F7861900 FD4683E0 1A Edge 01 i8042prt!.text+1600
/ j, U, w' s% U( O# A4 I9 `FD348D88 3C F786798C FD35D020 0F Edge 01 i8042prt!PAGEMOUC+020C/ k# i0 a0 g* w: ]) g7 s4 c
FD189708 3D FC8F22C0 00000001 0E Edge 01 WINDRVR!.text+2040
$ O" n. `! a5 j1 d" T3 V' zFD48F788 3E FD10FE42 FD4BD030 0D Edge 01 atapi!.text+5AE2
7 t8 r* l) E$ G/ j4 RFD34A888 3F FD057AA0 FD34E0DC 0C Level 01 NDIS!PAGENDSM! Q9 I; d( q. H# @
NTICE: Exit32 PID=70 MOD=ps2_diag
& F: |. k0 R5 a, a
5 S1 \% c4 @. N* j% s从上面可以看到,0Eh(即14)号硬件中断被映射到了IDT的3Dh项。还不相信吗?好,让我们来测试一下。在SoftIce中敲入如下的指 令:genint 3d,看到什么了?呵呵,屏幕显示如下:5 U% x+ T% ]/ n0 z

$ h+ t4 {$ {+ \8 i2 {
9 N" a" H  ?, ^2 _! W* Z/ h; h4 v5 j" s/ _0 Y/ O8 E
我们用:genint 3d这条指令模拟了一次硬件中断,结果表明我们的ISR确实是挂在了IDT的3Dh项处。在Softice中再运行几次genint 3d试试 看,屏幕上会输出什么样的结果呢?当然是Got Interrupt0 number 2,Got Interrupt0 number 3之类的信息啦。  w, b' u5 R% x- i
' q" E( w& U* F. S6 R
一个问题马上被提出来了
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 21:29 , Processed in 0.426287 second(s), 52 queries .

回顶部