这个SideKick是个好东东。 D_v
bSF)
rtc9wu
下面的程序不是我写的。 _%QhOY5tv"
=UV`.d2[
用汇编编写DOS下的内存驻留程序(1) =:~R=/ZXk
l+V>]?j
M![J2
=
i':C)7
jy'13G/b\
&RfC"lc
R?]02Q
绪言 8@tV9+u
=Q\r?(Iy
ti#7(^j
0.1 内存驻留与中断 Dc
,I7F|%
x&0vKo;
EAM5{Nc
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 c"[cNZo
1YH+d0UGn
^pUHKXihD
内存驻留程序的常用形式有: .0es3Rj
Hro-
d1J7
SJHr_bawd
>诸如Borland 的SideKick弹出式实用程序 6O
y$gW)
P'_H/r/#
Mxv;k%l|E|
>日历系统 *c2YRbU(
wp&=$Aa)'
[sW3l:^
>网络服务器 j
:VbrR
x9JD\vZ
:8OZ#D_Hl
>通讯程序 @H=:)*;
<[-nF"Q
2 O%`G+\)
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) <*qnY7c&N;
P}4QQw
h D/*h*}T>
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. [C'JH//q*t
-X"p:=;j
R#I0|;q4|p
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: 3eF-8Z(f
a*&B`77`|
w9bbMx
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. P(f0R8BE
jEZMUqGY!
\RG8{G,
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. H5Io{B%=
5;YMqUkw
J|qZ+A[z
>以上各种的结合. =o$sxb
E(
s6@DGSJ
LA}Syt\F
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. tIuCct-
VcXq?f>\
}n>p4W"OM
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. BW$"`T@c6~
fSokm4]vg
z62;
cv
手式计算中断向量的首址,可通过以下的公式来求得: i uF*.hc,%
0E3[N:s
yjF1}SQ
X号中断向量的首址=0000H:X*4 '2 PF
!]=d-RGNe
H<PtAYFS
当产生一个中断时,处理器都按顺序执行以下步骤: {y_98N
r2,.abo
q-}Fvel u
>在堆栈上压入处理器的标志(相当于指令PUSHF). T[g[&K1Y
=ACVE;L?
T9Nb`sbV]
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). pu2tY7Ja
Y!nJg1
?j"KV_
>关闭中断(CLI) @}}$zv6l,
,X`)ct
iT2B'QI=<
>从中断向量加载的CS和IP,执行中断处理程序. gaZu;t2u
xHD=\,{ig
e,W%uH>X
当执行完中断处理程序后,一般用IRET返回,它的作用是: }&wUr>=
ww],y@da
,F,X
,
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). CEX"D`
YoBDvV":@
@`q:IIgW
>同时恢复中断前的处理器标志(相当于指令POPF). e
&&53?
x-^`~p
lPw%ErG
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. Z{]0jhUyNh
K/IWH[
;V *l.gr'2
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. .\)U@L~
_./Sk|C
RO 4Z?tz
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. &L'Dqew,*
Nn!+,;ut
Vex{.Vh,"
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. Cv6'`",Yzm
xMTKf+7
,(EO'T[
S[PE$tYT#t
0.2 DOS的可重入性分析 1_PoqD!q
{zQ8)$CQ
9\_eK,*B
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. #49kjv@
>\KNM@'KI
E&2OD [iX
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. bk;?9%TW
0i!u
UF
TO]@
Zu1
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: J}v}~Cv
F \KjEl0
xhVO3LW'
Add proc near &"&Z
#llb
Enum/O5
n<O}hM ZT
cmp DS:word ptr [si],0 zv0l,-o
J^SdH&%Z
_>(^tCo
je DonotAddTheValue p<2L.\6"
WW4vn|0v
QbkLdM,S*
add ax,DS:word ptr [si] gQ Fjr_IS#
Br1&8L-|%
JTSlWq4
DonotAddTheValue: J??-j
kMi/>gpQ
le/,R@]B9
ret 1OCeN%4]Qk
+B B@OW
IzikDc10
Add endp ?!A7rb/tj
T@2#6Tffo
a{^m-fSaR"
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. _(%d(E2?
Z}mLLf E
hYPl&^
mov ds,0100h ;ds=0100h "p_J8
a,
k'Vk{
G_bG
mov si,0010h ;si=0010h 2@'oe7E
E ~Sb
n.!#P|
mov ax,0001h ;ax,=0001h >,gg5<F-E
ORe(]I`Z
nAW:utTB
call Add m0ER@BXRn
#5cEV'm;
!h"Kq>9T
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine JEXy%hl
g!@<n1 L
iU$] {c2;A
push ds ;Interrupted \?[v{WP)
DS+}UO
{ C=NUK%?
push si cv998*|X:
y"bByd|6
PRu 6xsyA
push ax t<#mP@Mz=N
[Dk=? +
#
hfXZVD
mov ds,0200h ;ds=0200h 4|buk]9
IUE~_7
adCU61t
mov si,0200h ;si=0020h @$S+ Ne[<
(G zb
IHam 4$~-
mov ax,0003h ;ax=0003h v- T$:cL
G18F&c~
.k,1f*%
call Add wvO|UP H\
$?Yry.2
)97SnCkal
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h 0
HGM4[)=
Dv| #u|iw
Y-kt.X/Z-
jne sF!($k;!
%HGD;_b
hI
|n+qMql'
add ax,0200h:word ptr [0020h] ;ax=0007h _ky,;9G]
UW N*j_9i
d"}k
!
0m
ret ;Return K&POyOvT
t2/#&J]
wQqb`l7+
pop ax ;ax=0001h E27vR 7
]op}y0
6h|q'.Y
pop si ;si=0010h jN
{Xfjmfv
D^yRaP*|7
f[<m<I
pop ds ;ds=0100h F_w
Z"e6
0Vlk;fIh
KK&rb~
iret ;Return to Add subroutine ?I6fye7
F"&~*m^+
od IV:(
jne >zw.GwN|
'Y*E<6:
nxUJN1b!N
add ax,0100h:word ptr [0100h] ;ax= 0001h '8Q]C*Z
o<|cA5f\
>.Chl$)<
;0100h:0010h= 0002h qaY1xPWz"
!nqUBa
\w/yF4,3<w
;---------------------------------------- f\]sz?KY
rSZd!OQ
w`4=_J=GO
;ax = 0003h $+P>~X)
Q\^O64geD
>6NRi /[
ret 13 =A
pXrFljoYl[
}#L^! \V}
mov bx,ax v25R_""~
/xsF90c\h
p`b"-[93
而下面的子程序是不可重入的: R n}l6kbM
wT;0w3.Z
o|>'h$
Add proc near *,e:]!*
uD\?(LM
kE:nsXI
)
mov Temp,ax zz+$=(T:M
[b6R%
@G8lr
mov ax,DS:word ptr [si] &M46&^Jho
_wTOmz%|R
M9!HQ
cmp ax,0 5Sm}nH
m_.>C
\n$u)Xj~6^
je DonotTheValue G9Y#kBr
*!q1Kr6r
4lr(,nPRD
add ax,Temp 6g 5#TpCh
Bzkoo J
}=%oX}[
DonotTheValue: =
Q+;=-1
2;zb\d
hlV=qfc
ret "Ue.@>
!Fca~31R'
GC>e26\:
Temp: '10oK {m$
{9?Jj A
[BWNRC1
dw 0 -K
q5i
<oR a3Gi(%
/I1h2E
Add endp +fC=UAZ