这个SideKick是个好东东。 X\m\yv}}
Ss%Cf6qdWL
下面的程序不是我写的。 K[icVT2v~
}>6e-]MHfR
用汇编编写DOS下的内存驻留程序(1) dM;\)jm
lMFo)4&P
J:Fq i p
AAQ!8!
|aP`hVm
f5*qlQJFz\
^UKAD'_#%O
绪言 Z4
i))%or
C7dq=(p&
>pp/4Ia!
0.1 内存驻留与中断 hV(^Y)f
sMMOZ'bT
C>Hdp_Lm
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 F- -g?Q^
',R%Q0Q
3WP\MM
内存驻留程序的常用形式有: @/^<9
$sY'=S
G[ U5R?/
>诸如Borland 的SideKick弹出式实用程序 \oWpyT _
`o{ Z;-OF
)8C`
EPe
>日历系统 \ UrD%;sq
JPZp*5c6A
X|a{Z*y;r*
>网络服务器 5a/A?9?,
]owgsR
P*!`AWn
>通讯程序 nms[No?
$_F_%m"\
)xy>:2!#Y
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) >1
`4]%
r<ww%2HTS
]jD\4\M}
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. C4(xtSJSd!
#ELeW3
S}
![%wM Pp
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: r2SZC`Z}-M
oYN"L
?^Aj\z>
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. 1Of(O!
b@CjnAZ
<XLaJ;j
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. %/uLyCUZ
/''=V.-N
O5r8Ghf)
>以上各种的结合. /p<9C?
J>v[5FX+
W!<7OA g $
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. @.7/lRr@bp
G{[w+ObX
JlnmG<WLT
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. )IcSdS0@M
<KX9>e
~Y`ys[Z m
手式计算中断向量的首址,可通过以下的公式来求得: D`@a*YIq
F{jxs/~
PV#h_X<l%
X号中断向量的首址=0000H:X*4 o6A$)m5V
HVus\s\&y%
rhkKK_
当产生一个中断时,处理器都按顺序执行以下步骤: UK,bfLPt~
:O413#8
t[TM\j0jW
>在堆栈上压入处理器的标志(相当于指令PUSHF). zd5=W"Y;]
^mq(j_E.
j;.P
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). lPZ>#
gfK_g)'2U
0 8)f
>关闭中断(CLI) CaZc{
U^KWRqt
bRu9*4t
>从中断向量加载的CS和IP,执行中断处理程序. Z5v_- +K
;J|t-$Z
Az@@+?,%Y
当执行完中断处理程序后,一般用IRET返回,它的作用是: X[$h &]
F%
n}vA`
{LjzkXs
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). ^>E>\uz0v
4tkT\.
Q&W>h/
>同时恢复中断前的处理器标志(相当于指令POPF). \'Ca1[y@B
HK :K~h
b|-)p+ba
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. MtL<
)?HQ
kS_#8I
8$~oiK%fw
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. @ovaOX
we_CF*zj
9xbT?$^
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. xy:Mb =r
L'Cd`.yVO
6qDt6uB
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. %!t9)pNc
#~'d
Y\&
]D;*2Lw4&
:PBFFLe
0.2 DOS的可重入性分析 xwo*kFg
bhpaC8|
f~W+Rt7o
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. 9_wDh0b~p
JL4E`
}6^5mhsL
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. L E\rc A
y ]t19G+
iT&4;W=72~
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: rSv,;v
*DIY;)K
Lx>[`QT
Add proc near Jw5@#j
?jz\[0)s
|kh{EUE
;
cmp DS:word ptr [si],0 EHq;eF
e'uC:O.u
]*=!lfrV
je DonotAddTheValue =iB[sLEJ
p^ (Z
0p.MH~mx
add ax,DS:word ptr [si] }IWt\a<d
gd
* b0(
BEvt{q4
DonotAddTheValue: t
RI<K
sxr,]@
fNi&r0/-t
ret
lha;|
X~&8^?
$yi:0t8t
Add endp MH)V=xU|)
Ub
f5:
47(_5PFb#
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. CN(-Jd.b
_w\i ~To!
b;D
mov ds,0100h ;ds=0100h _*UI}JtlS
{Y5@SIyE
I)yaR+l
mov si,0010h ;si=0010h "0%K3d+
)U|V |yem'
.f0qgmIyL
mov ax,0001h ;ax,=0001h 6I RRRt O(
GXm#\)
MJX4;nbl
call Add (hOD
kntY2FM
;76+J)
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine y@v)kN)Y9\
,sSo\%
jY\z+lW6A
push ds ;Interrupted 3r#['UmT
i. )^}id
muXP5MO
push si Q\s+w){f%
%r.OV_04
_O}U4aGMTC
push ax '^m'r+B"
\(7A7~
,{G\-(\
mov ds,0200h ;ds=0200h R\ 8[6H
EGI$=Y
3.Mpd
mov si,0200h ;si=0020h P9m
#y: F3$c
9Vq
mov ax,0003h ;ax=0003h q !9;JrX
rAtC
G1Vr
h8O\sKn
call Add ;bG?R0a
GU`q^q@Ea
XK\nOHLS
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h j5R0e}/r
}Ifa5Lq)
l[_antokn
jne h1(i/{}:
0xDn!
!G vT
{
add ax,0200h:word ptr [0020h] ;ax=0007h =Pn"nkpML
>"1EN5W
(M|DNDM'd
ret ;Return Q?T+^J
(KN",u6F
~Y
f8,m
pop ax ;ax=0001h xU%]G.k
$k)K}U
E4o{Z+C
pop si ;si=0010h 9c4p9b!
qbSI98rw
zjA#8;h~w
pop ds ;ds=0100h {hN\=_6*EW
+dLUq2
/"="y'Wx
iret ;Return to Add subroutine M
2|
k.
Wn6m$ =
075IW"p'
jne uSYI
X
c.1gQy$}|
H(K!{k
add ax,0100h:word ptr [0100h] ;ax= 0001h V?*fl^f
2hNl_P~z1u
Ga9iPv
;0100h:0010h= 0002h $X
;OK
$- ]G6r
H0tu3Pqk
;---------------------------------------- 5N>f l
Q
d, g~.iS~
1P*GIt2L
;ax = 0003h c}$>UhLe
CLZj=J2
=Bc{0p*
ret %JPr 7 }
O[$X36z
ea @
H
mov bx,ax kD+#| f
N:Q.6_%^
tk-)N+M.
而下面的子程序是不可重入的: PW%ith1)<
NUb$PT
!wE% <Fh
Add proc near :RIqA/
ORKJy)*"
"LDNkw'
mov Temp,ax p q?# X0
zqU$V~5;rG
yj'lHC
mov ax,DS:word ptr [si] $X:,Q,?
jtfC3E,U
|O)ZjLx
cmp ax,0 `K0.6i [p
<,p$eQ)T%
mpD.x5jm<
je DonotTheValue ~)$R'=
yn+m,K/
Ff0V6j)ji
add ax,Temp jqvw<+#
6(?@B^S>2
U~sC%Ri-@U
DonotTheValue: E`HA0/
!7~4`D
c6U
Am3j:|>*
ret `Ivt)T+n;
o$->|
k
g,*fpk
Temp: XFs7kTY
8?m=Vw<kIZ
um]N]cCD`
dw 0 _}j>
65@GXn[W_
WxD
$k3U
Add endp f#AuZ]h