这个SideKick是个好东东。 \Eqxmo
gG5@ KD6k
下面的程序不是我写的。 *htv:Sr
VsLlPw{
用汇编编写DOS下的内存驻留程序(1) Z1u:OI@(
;oL`fQyr
?&v+-4%4PI
6, =oTmFP
-U'3kaX5<
9cV;W \ Tw
)q#1C]7m*
绪言 dk}T&qZ~p
g?Jx99c;
aH@GhI^@
0.1 内存驻留与中断 zW[fHa$m
Z*,Nt6;e
+"8AmN4
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 ;Oh abbj*
=/_tQR~
GI:J9TS
内存驻留程序的常用形式有: dS9L( &
YXeL7W
}@VdtH
>诸如Borland 的SideKick弹出式实用程序 qo,uOi
eRV4XB :
wLX:~]<xl
>日历系统 e6O +hC]:
0|mF
/
3eOwy~
>网络服务器 =Yd{PZ*fR
lN@SfM4\
;fg8,(SM^
>通讯程序 zT
_
l]:nncpns
+
Xc s<+b
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) E RnuM
II=(>G9v
V)HX+D>
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. 1D@'uApi
.
sw:o3cC]
WKjE^u
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: d5aG6/
){'Ef_/R
Z1@E
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. ?f}lYQzM
POZ5W)F(
7r,s+u.
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. ^o;f~6#17
uU+R,P0
bU3e*Er
>以上各种的结合. (~}P.?C8
cu)ssT
u;-_%?
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. 0f"9wPC
/HlLfW
T~=r*4
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. ?_hKhn%K9
H);O.
m
e
N]AJ%Ig
手式计算中断向量的首址,可通过以下的公式来求得: 8 K7.; t1
OC(S"&D
"t[9EbFL
X号中断向量的首址=0000H:X*4
>gQJ6q
HLD8W8
6R.%I{x'
当产生一个中断时,处理器都按顺序执行以下步骤: e|6kgj3/
zk#NM"C+
~ 9F
rlj
>在堆栈上压入处理器的标志(相当于指令PUSHF). 2h_XfY'3pX
y;'yob
i .O670D
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). '>8IOC
<FaF67[Q
B~\mr{|u
>关闭中断(CLI) 8mrB_B5
Rw
j4
U%<E9G594
>从中断向量加载的CS和IP,执行中断处理程序. [;/4'
7EI5w37
blUnAu
o~
当执行完中断处理程序后,一般用IRET返回,它的作用是: o8PK,!Pl
Bf)}g4nYn
DQ
#rZi3I
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). df85g
mNc?`G_R
Z$a5vu*pg
>同时恢复中断前的处理器标志(相当于指令POPF). Z%rMX}
bSG}I|
//x^[fkNq)
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. f1Az|h
G)(vd
0X1
lKtA.{(
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. 1KHFzx,
8ztVv
/b|V=j}W
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. nM=5L:d
d*}dM"
-[h2fqu1
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. YI877T9>
){D
6E9
JY5
)^<.d
_S$SL%;\
0.2 DOS的可重入性分析 xJ&E2Bf
PUU
"k:{
QsO%m
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. \/wbk`2
C>}@"eK
%>)HAx `
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. GBh$nVn$
Lm!/iseGv
>
+/2g
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: MAv-`8@|
>e'Hz (~'/
5.IX
Add proc near pW
y+oZ
tz
6N,4J?
M/d6I$~7z
cmp DS:word ptr [si],0 B.S
zp_$
P(Gv|Q@
k <EzYh
je DonotAddTheValue b +4x2{
uV|%idC
dE_
d.[!
add ax,DS:word ptr [si] EF8~rKO3
]"wl*$N
C6PlO
DonotAddTheValue: d~|/LR5
0%W0vTvL
p;x3gc;0
ret "sD[P3
_aaQ1A`p
~;QzV?%
Add endp q{c/TRp7
='[J.
lTR/o
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. ?=},%^
~MpcVI_K
##\
<mFE
mov ds,0100h ;ds=0100h Xc}~_.]
FD1Z}v!5IJ
.='hYe.
mov si,0010h ;si=0010h H\PY\O&cP
m4m,-}KNi
<N~&Leh
mov ax,0001h ;ax,=0001h o8ERU($/
L>ruNw'-K
#~JR_oQE!
call Add x%`.L6rj
g[%iVZ
!vY5X2?tr,
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine `Lr I^9Z
,zP.ch0K
|eu:qn8
push ds ;Interrupted E*W|>2nx]
S 9;:)
9 aacW
push si aCZ7G
%Y
j@guB:0
!RPPwvNk4
push ax U4.-{.
;+Sc Vz
NDo>"in
mov ds,0200h ;ds=0200h 37U2Tb!y'
qt.Y6s:r_
;,2;J3,pA
mov si,0200h ;si=0020h D8O&`!mf
/ygC_,mx
Cvgk67C=$
mov ax,0003h ;ax=0003h .B? J@,
kw$*o
k
|'SgGg=E
call Add -]-?>gkN5
hLo>jE
k3-7Vyg
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h .~C[D
T+,
BXxl-x
G,-x+e"
jne
TNj WZ
g-NfZj?
qy^sdqHl@
add ax,0200h:word ptr [0020h] ;ax=0007h D&]dlY@*
D:I6nSoC
F<Y>
ret ;Return 8j^3_lD
:dML+R#Ymh
rP<S
=eb
pop ax ;ax=0001h Eo@b)h
CW .
O"_
79y'PFSms
pop si ;si=0010h 0,M1Q~u%.
Y )](jU%o
=K`]$Og}8
pop ds ;ds=0100h wF.S ,|
*D:"I!Ho
_c@k>"_{S
iret ;Return to Add subroutine yu98d1
.8~zgpK
[}1+=Ub
jne ,enU`}9V*
'>aj5tZ>R
wS%j!|xhlV
add ax,0100h:word ptr [0100h] ;ax= 0001h M?3#XQDvD
bi<?m^j
eI:;l];G9
;0100h:0010h= 0002h sR*.i?lN
?]Wg{\NC6
=.9uuF:
;---------------------------------------- .0ExHcr
E==vk~cz
+}-Ecr
;ax = 0003h ]4
q6N
]*\m@lWu
WVkJ=r0Ny
ret JQdeI+
>6\rhx
>
a?gziCmS?C
mov bx,ax jC3)^E@:"
w}:&+B:
W:TF8Onw
而下面的子程序是不可重入的: @`S8d%6P
m!H7;S-(
fo$Ac
Add proc near 'H|=]n0
9+"\7MHw
:,*{,^2q:
mov Temp,ax k,M%"FLQ
=3R5m>6!/
5IfyD ]<
mov ax,DS:word ptr [si] XL2iK) A
go[(N6hN
P+s-{vv{0
cmp ax,0 $ri
'tJ+
h}@)oSX
}
7O^'?L<C'
je DonotTheValue )gb gsQZ
k2t#O%_f
P{
{U
add ax,Temp %J?"ZSh
Q ,6
[
_6/q.
DonotTheValue: Ua](o H
B
(l8&
yw{;Qm2\7
ret |v?*}6:a
<&Q(I+^
7$HN5T\!
Temp:
uZA^o
S-D=-{
@
Zyx92z9Y
dw 0 W%.ou\GN^t
}ki}J >j|f
A\S1{JrR
Add endp g#b uy