这个SideKick是个好东东。 m7mC
7x
XlNB9\"5
下面的程序不是我写的。 .^1=*j(;
xhMdn3~U
用汇编编写DOS下的内存驻留程序(1) Ix5yQgnB}j
t!Av[K
Un[#zh<4
3?/}
G}~b
gzdgnF2
#$fFp
绪言 C{S6Ri
~yf 5$~Z
Z=sAR(n}~
0.1 内存驻留与中断 }mJ)gK5b 6
mKq9mA"(E
AB#hhi#
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 I`KN8ll
qOa-@MN
e S
Fmx
内存驻留程序的常用形式有: PwNLJj+%
Bp6
Evi
I3aEg
>诸如Borland 的SideKick弹出式实用程序 vqxTf)ys
(/Y
gcT
\J\1i=a-=
>日历系统 -)<Nd:A
QnOa?0HL/
f%auz4CZz
>网络服务器 khu,P[3>
~E`A,
Qg oXOVo6
>通讯程序 @fYA{-ZC
"ChBcxvxb:
~d5{Q?T)
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) QU4'x4YS
T
+4!g|Y
)d1,}o
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. C"mb-n7s
;[zx'e?!
n:!J3pR
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: 1X9sx&5H
Y2D)$
*'t`;m~
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等.
nocH~bAf2
V[#lFl).
,!py
n<_
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. \1B*iW
O 1X
!
02S(9^=
>以上各种的结合. p9sxA|O=y
(c*Dvpo1
6<~y!\4;F
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. E0h!%/+-L
{DO9{96w4
%yrP: fg/
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. bo"I:)n;
D 7E^;W)H
]ogy`O >
手式计算中断向量的首址,可通过以下的公式来求得: nMbV{h ,
T<=\5mn
Cw2+@7?|
X号中断向量的首址=0000H:X*4 t[
MRyi)LF
G0&w#j
bU,&|K/
当产生一个中断时,处理器都按顺序执行以下步骤: q
B2#EsZ
'}Y8a$(;V
&]c9}Ic
>在堆栈上压入处理器的标志(相当于指令PUSHF). xX
>448=
U)o8Tr
4'8.f5
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). / q!&I
@<sP1`1
|ZKchd8Yq
>关闭中断(CLI) ~gDtj&F
t-Fl"@s
<z4!m/f[(
>从中断向量加载的CS和IP,执行中断处理程序. J\0YL\jw1K
y@z#Jw<
Stw6%T-
当执行完中断处理程序后,一般用IRET返回,它的作用是:
Te13Af~
VEZ/-s/
fjJIF%
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). ,J#5Y.
>) ^!gz8
Q'Tn+}B&
>同时恢复中断前的处理器标志(相当于指令POPF). d$Xvax,C
-
|'wDf?H
OWkK]O
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. t8[:}[Jx
ZtT`_G&
P$QfcJq&c*
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. 3WVHI$A9
O#|E7;
M;bQid@BG
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. S {H8}m|MW
m
;vNA
_B[(/wY
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. yiU dUw/
32Z4&~I
w$!n8Aqs
wDG4rN9x
0.2 DOS的可重入性分析 <.2Z{;z
!1_:n D
G7<X l}
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. Tk:y>P!%a
KP(Bu0S
Pg36'aTe%j
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. lo#,
zd~
>JMKEHl.q
xVPGlU
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: Ui.F<,E
aU! UY(
m}E$6E^~O
Add proc near Xz@>sY>Jc
1,J.
td~3N,S
cmp DS:word ptr [si],0 ?~{xL"
xl^'U/
YGO@X(ej,
je DonotAddTheValue `xr%LsNn
$} Myj'`r
fYi!Z/Ck2
add ax,DS:word ptr [si] \4[Ta,;t
.,,73"
hd B[H8Q
DonotAddTheValue: {mQJ6
G'ny
v>5F[0gE
y()( 8L
ret gr=`_k4~1
[`lAc V<
)em.KbsPPF
Add endp vX\e*
v
AQ5v`xE4
uwka 2aSS
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. >A/=eW/q
1DP)6{x
\v_C7R;&
mov ds,0100h ;ds=0100h dw|0K+-PH
GdU
W$.
2v
C=.1k
mov si,0010h ;si=0010h ;~J~
g#
jo
*9QO
K&h6#[^\d
mov ax,0001h ;ax,=0001h e{,/
=!X4j3Cv
u|c+w)a
call Add NsHveOK1.
u/f&Wq/
A.b#r[
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine a6d KQ3D
_u>>+6,p
(Wqhuw!u
push ds ;Interrupted :Eyv= =
u"jnEKN0y
I .ty-X]
push si K;PpS*!
8g NEL+
!)=o,sVA
push ax %U7B0-
a5M>1&j/eC
Ul
Iw&U
mov ds,0200h ;ds=0200h a
p~Iz
De_</1Au!2
p rgjU
mov si,0200h ;si=0020h [)A#9L~s=
bph*
X{lFK
w$4Lu"N:
mov ax,0003h ;ax=0003h ?r<F\rBT7*
P>-,6a>
xJhbGK
call Add
Biwdb
=.a ]?&Yyh
[
UJj*n
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h
P+0xi
s|'L0` <B
`9l\~t(M
jne v3Yj2LSqx
@\?f77O
f6
ise}> A!t
add ax,0200h:word ptr [0020h] ;ax=0007h h'p0V@!N
sh2bhv]
MVdx5
,t
ret ;Return
rE:>G]j6
vNbA/sM
eZi<C}z
pop ax ;ax=0001h ~tvoR&{I
$@)d9u
cd
b3lpNJ J
pop si ;si=0010h : 4WbDeR
X;:xGZ-oY
r
`dU
(T!
pop ds ;ds=0100h P}`1#$
ex458^N_
=jt_1L4
iret ;Return to Add subroutine xF;v 6d
rUjr'O0
N sL"p2w~
jne !%r`'|9y
,m,vo_Ub
"S:N-Tf%U
add ax,0100h:word ptr [0100h] ;ax= 0001h lv*uXg.k^
w ZAXfNA
'wrpW#
;0100h:0010h= 0002h -;$/<
2\de |'
Fr3t[:D
;---------------------------------------- x["
nif'l/@"
Rn_c9p
;ax = 0003h 9lCKz
!E
rgKn=8+
a
Ui
!|!V-
ret FOi`TZ8
YPnJldVn
zP}v2
mov bx,ax Pltju4.:C
sEyl\GL
{2^@jD
而下面的子程序是不可重入的: &NeYKh?
5i#w:O\cz
,r;d {
Add proc near +=Wdn)T
9G+rxyWMW
/H@")je
mov Temp,ax ~+yo;[1Yc
ycD.:w p\'
wtS*w
mov ax,DS:word ptr [si] A>A'dQ69
W2qQKv
V JL;+
cmp ax,0 5Suc#0y
22~X~=
l$_rA~Mo
je DonotTheValue 79g>7<vp
GQq'~Lr5
T
l(uqY?9
add ax,Temp /ASI0h
uTGvXKL7
Tpx,41(k
DonotTheValue: WI_mJ/2
7,UFIHq
%0]b5u
ret
}92lr87
6 JYOe
}Xv1KX'
Temp: D(U3zXdO
F5P{+z7
agT[y
/gb
dw 0 e~]e9-L>I
"IJMvTmj
[Od9,XBa
Add endp h##?~!xDmq