这个SideKick是个好东东。 mp sX4
2l V`UIa
下面的程序不是我写的。 yO8@ .-j b
AX+]Z$
用汇编编写DOS下的内存驻留程序(1) z"7?I$NQ
]6v7iuvI
n7ZJ< ~wl
V]Ccj\Oi
6v:L8t$"
%jj-\Gz!
)cQ KR4x0^
绪言 xG
edY*[`
GBg
/J-.K*xKt
0.1 内存驻留与中断 3nhQ^zqf
9({ 9 r[U
6w3[PNd
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 d<ES
)N^fSenFBn
?\4kV*/Cqz
内存驻留程序的常用形式有: [8tpU&J
hA/Es?U]
)2W7>PY
>诸如Borland 的SideKick弹出式实用程序 ho^c#>81
p[WlcbBwT
?S=
y>b9R
>日历系统 4?(=?0/[
X0ugnQ6
k
"7,-0gz
>网络服务器 *j,noHUT~>
j3w~2q"r
"S{GjOlEDF
>通讯程序 &~.|9P/45
U%1M?vT/
dQH8s
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) UjunIKX+
q2B'R
~a7@O^q4
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. \hlS?uD\
_z]v;Q
w(+L&IBC
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: Wn;%B].I
$M-"az]
|iSwG=&
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. L28wT)D-
;
1?L
/;q3Q#
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. jsV1~1:83
4s>L]!
W$8
9(=+OQ6
>以上各种的结合. 1GR|$E
g] IPNW^n
IYptNR
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. Ls|)SiXrY
WQw11uMt@q
#>CWee;
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. rjfWty%6pX
AxJqLSfyb,
j";L{
手式计算中断向量的首址,可通过以下的公式来求得: <Cs
9$J
\mb@-kM)
VWXyN
X号中断向量的首址=0000H:X*4 0V"(}!=2a
<|WXFjn
&kWT<*;J)
当产生一个中断时,处理器都按顺序执行以下步骤: S9b=?? M)
NV}fcZ
OHngpe4
>在堆栈上压入处理器的标志(相当于指令PUSHF). Q-s5-&h(
buKkm$@w
="@f~~
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). z:O:g?A
fE|"g'
c0jTQMe4yl
>关闭中断(CLI) 9ygNJX'~
I)3LJK
-ImO y|
>从中断向量加载的CS和IP,执行中断处理程序. %dmQmO,
)99^58my
S[8nGH#m
当执行完中断处理程序后,一般用IRET返回,它的作用是: <dS I"C<
0 >(hiTy<
)!zg=}V
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). xw~oR|`U
4ee-tKH
T9}dgf
>同时恢复中断前的处理器标志(相当于指令POPF). A5}N[|z
f0g_Gn $
A$P Oc<
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. i-95>ff
:%fnJg(
6]!Jo)BF
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. c2gZ<[~
HsG3s?*
6I]{cm
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. - sq=|
/^si(BuC^*
!YM:?%B
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. bWCtRli}
iy8Ln,4z(
h}m9L!+n8
j6*e^
B
0.2 DOS的可重入性分析 7|ACJv6%9
?v+el,
*m&'6qsS
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行.
0|\A5
eG
#cJ1Jj $
M6Ik 'r"M
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. U;
#v-'Z
z+_d* \
>^@~}]
L
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: =.`e4}u \X
_lH:%E*
(w<llb`]
Add proc near 7/=r-
(c3O> *M
UY\E uA9
cmp DS:word ptr [si],0 C1YH\X(r
@9]TjZd
loyhNT=
je DonotAddTheValue (r.y
gazX2P[D
&$pQ Jf
add ax,DS:word ptr [si] O+DYh=m*p
77]Fp(uI
/5>A 2y
DonotAddTheValue: PC,I"l
VB+_ kR6Zv
RbA.&=3
ret oBPm^ob4
8js1m55KT
0w2<2grQ
Add endp
y?*Y=,"
]>+ teG:4
)5diX
+
k
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. p{0rHu[
xiC.M6/
JAmpU^(C
mov ds,0100h ;ds=0100h 0)vX
){tT
B
)h%tEY$AJ
mov si,0010h ;si=0010h 2-#&ktM%V
<5|:QLqy
{I$zm
VG
mov ax,0001h ;ax,=0001h wX@g>(
,F|49i.K
%x^ U3"7
call Add 8hX/~-H
Og2w]
B[
x)kp*^/
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine y 5Kr<cF^
.T~Oc'wGo
sdQ"[`~2R
push ds ;Interrupted K>2 Bz&)
I^``x+a
SQG9m2
push si r
;zG
U]E~7C
7*Gg#XQ>(
push ax ^{O1+7d[.
T'
)l
?j8_j
mov ds,0200h ;ds=0200h FbD9G6h5
s<LYSr d
R36A_
mov si,0200h ;si=0020h {%Q+Pzl.
O
0P4uq
w[;5]z
mov ax,0003h ;ax=0003h thh0~g0/
V9D>Xh!0H
0*/[z~Z-1
call Add [@$t35t~
5q}7#{A
OJ#
d
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h U,\t2z
~N+H7T.L
l4E0/F
jne bqZ5GKUo
0ol*!@?
~5~Cpu2v7
add ax,0200h:word ptr [0020h] ;ax=0007h D'_w
*
N*}g+IS
J}VG4}L
ret ;Return S1*xM
g % 8@pjk
u5P2*
pop ax ;ax=0001h kK]L(ZU+
K@!Gs'Op
>s;dooZ
pop si ;si=0010h Fau24-g
Vfr.Yoy
yt`K^07@
pop ds ;ds=0100h lM%3 ?~?Q&
h}GzQry1
14 hE<u
iret ;Return to Add subroutine ]M&KUgz
/V>yF&p
@t#Ju1Y
jne =?1B|hdo
IKeO&]k
f2M}N
add ax,0100h:word ptr [0100h] ;ax= 0001h &>Nw>V
U!524"@%U`
V.kf@
;0100h:0010h= 0002h Uj)`(}r
yT C+5_7
^
r
9
;---------------------------------------- SGLU7*sfd
G9ra;.
qZh}gu*>
;ax = 0003h ggzcANCD<
z7O$o/E-*
6"U$H$
i.G
ret c"S{5xh0&
m+dJ3
iq`caoi
mov bx,ax o;{BI
Q1
ys}I~MK -
J4m2|HK
而下面的子程序是不可重入的: 6tBe,'*
;v%f +
N?mQ50o~C
Add proc near = _/XFN
Ibu 5
sK|+&BC
mov Temp,ax >B+!fi'SS>
;Z-%'5hKM
_h P7hhR
mov ax,DS:word ptr [si] Au{J/G<W@
d01]5'f?o
nW_cjYS%
cmp ax,0 =a_ >")
:sJQ r._L
LVBE+{P\5?
je DonotTheValue
D~t
P^m&oH5]EG
w@hbY:Z9z
add ax,Temp }Gh95HwE
0hOps5c8=
/
#D R|
DonotTheValue: 5P![fX|5
@@#h-k%k-
"|d# +C
ret )
8JM.:,
\) g?mj^
LCemM; o
Temp: a/lTQj]A
9<1dps=c
t'bhA20Z\
dw 0 7toDk$jJRg
*f3?0w
uwWKsZ4:ij
Add endp /zIUYY