这个SideKick是个好东东。 <VSB!:ew
'J3yJ{
下面的程序不是我写的。 L>mM6$l
` &bF@$((
用汇编编写DOS下的内存驻留程序(1) Z6rZAwy
,]nRnI^
6212*Z_Af
-#mN/
."gq[0_YS
O2?yI8|Jn
?@Q0;LG
绪言 a6cU<(WDeh
x2a
?ugQ
*C0a,G4
0.1 内存驻留与中断 g],]l'7H
[PB73q8
h Ypj
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 (F 9P1Iq
$_;rqTk]g
L)&^Pu
内存驻留程序的常用形式有: )+|wrK:*v
MgJ5FRQ
+nHr+7
}
>诸如Borland 的SideKick弹出式实用程序 60]VOQku
CM$&XJzva
po\jhfn
>日历系统 wN10Drc
;Z`a[\i':
}h1LH4
>网络服务器 SjpCf8Z(
_'17C/
pC0gw2n8M
>通讯程序 [s`B0V`04
xf/
K+
,A7:zxnc.V
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) bCr
W'}:de
mtkZF{3Jx
mdyl;e{0
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. QV.>Cy
"U"fsAc#
Dt> tTU 6
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: QH4m7M@ni
:\'1x
D\+x/r?-I
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. J%|;
p`rjWpH
GD)paTwO<
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. 8t=O=l\
jnbR}a=fJ
vea{o35!
>以上各种的结合. H ?9Bo!
}yn%_KQ0
!/tV}.*
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. H! 5Ka#B
("PZ!z1m1
-,YI>!
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. X@}7 #Vt
{D^
)%{
G7|d$!%
手式计算中断向量的首址,可通过以下的公式来求得: GM9[ 0+u;
k{lo'
3UW`Jyd`k
X号中断向量的首址=0000H:X*4 \m}a%/
>yLDU_P)
);AtFP0Y
当产生一个中断时,处理器都按顺序执行以下步骤: N\&VJc
$xdo=4;|
`7y3C\zyQ
>在堆栈上压入处理器的标志(相当于指令PUSHF). p7Zeudmj
1%vE 7a>{
wJJ|]^0.
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). $H.U ~
#<B?+gzFM{
p/Q<
VV
>关闭中断(CLI) ,mvFeo;@f
:h(3Ep
Og1\6Q
>从中断向量加载的CS和IP,执行中断处理程序. g.Qn,l]X/p
H_3WxfO
Rf8ZH
当执行完中断处理程序后,一般用IRET返回,它的作用是: h lc!}{$%8
1 oKY7i$
&&52ji<3
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). iG"v
tDah@_
x9\
{a
>同时恢复中断前的处理器标志(相当于指令POPF). r}e(MT:R'
x1`(Z|RJ
#:yAi_Ct
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. ^GrSvl}v'
l l*g *zt3
l{.PyU5)
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供.
M,p0wsj;
:|S[i('
PPrvVGP
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. f. >[ J
RA!m,"RM
EXjR&"R
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. 5wh(Qdib
0
%,W5w
YU0pWM
UtJfO`m9P
0.2 DOS的可重入性分析 EZ/_uj2&SN
BR?DW~7J j
e 2NF.
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. mZ? jpnd
+h/OQ]`/m
!Sy9v
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. U?|A3;
,xh
i( +Uv tgs
CdCY#$Z
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: g8&& W_BI
Gs|a$^
V|o
|x1Ttr,
Add proc near }id)~h_@
]e5aHpgR=
i !sVQ(:
cmp DS:word ptr [si],0 .Jg<H %%f
#P z'-lo
4IB`7QJq
je DonotAddTheValue {wt9/IlG1
muF&t'k
~2XGw9`J2
add ax,DS:word ptr [si] {yT<22Fl
|B$JX'_
>k@{NP2b
DonotAddTheValue: `FNU-
I4s
]
s 2ec
QD^= ;!
ret /8`9SS
5>CeFy
--TH6j"
Add endp s nxwe
Zn.S65J*u
g(s}R ?
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. NcwUK\
sA: /!9
i@WO>+iB
mov ds,0100h ;ds=0100h pX>wMc+
y6sY?uu
J32{#\By
mov si,0010h ;si=0010h ?wmu0rR
1 YtY=
bT9:9LP
mov ax,0001h ;ax,=0001h I
Gb'ii=A
wRwx((eb
xDekC~Zq
call Add v6aMYmenBH
H3d|eO4+W
'cQ`jWZQ
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine hHcevSr
#=Xa(<t
<?8cVLW}O
push ds ;Interrupted ;UX9Em
1
rbc}e
j+/EG^*/
push si )PU\|I0|)e
r
z@%rOWV
I 6<LKI/
push ax F/p1?1M
X3gYe-2
T
Q/#
mov ds,0200h ;ds=0200h P&5vVA6K7
X,o ]tgg=
b+ZaZ\-y
|
mov si,0200h ;si=0020h =yqg,w&Q
p((. (fx
p>pAU$k{O
mov ax,0003h ;ax=0003h HP 3%CB
?H!&4o
kaEu\@%n
call Add .g}Y!
l
w8>bct3@
j`3IizN2
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h PiR`4Tu
Of-gG~
@N>rOA
jne 7|"G
3ck
-ECnX/
"
jl]p e7-
add ax,0200h:word ptr [0020h] ;ax=0007h
b^8"EBo
^H<VH
>2mY%
ret ;Return 5y0LkuRR:
436SIh
[czWUD
pop ax ;ax=0001h Pj8Vl)8~NV
R5uz
<
)0;O<G] d
pop si ;si=0010h Xe/7rhov
FEa%wS{
#^i+'Z=L
pop ds ;ds=0100h /
dX,]OFm
d]=>U
^K
J[K>)@I/
iret ;Return to Add subroutine FuBUg _h
^MT20pL
Dn~t _n
jne ={ 190=\9
T[0CD'|E
MD> E0p)
add ax,0100h:word ptr [0100h] ;ax= 0001h <_bGV
*;t_VlaZ
]Qx-f*
D6
;0100h:0010h= 0002h o1]1I9
F>@z&a}(
?f:\&+.&
;---------------------------------------- X)9|ZF2`
m Ub2U&6(
)s 1
Ei9J
;ax = 0003h V+*1?5w
: NH'>'
D{[i_K
ret #?\|)y4i
&j{IG`Trl
cetlr
mov bx,ax !$o9:[B
J/ vcP
0b,{4DOD
而下面的子程序是不可重入的: jz&= 8
Gn10)U
f8X
!:g\Fe]
Add proc near FW<YN;
DshRH>7s8
)[t3-'
mov Temp,ax @(tuE
FEA/}*2F
i2Gh!5]f
mov ax,DS:word ptr [si] 3URrK[%x`
hM(Hq4ed,
U.WMu%
cmp ax,0 O}lqY?0*
etP`q:6^c
n^epC>a" b
je DonotTheValue ux7g%Q^"
$:D hK
R*O6Z"h
add ax,Temp }
/Iw]!lK2
jLul:*
L
VK4"
DonotTheValue: 3_ =:^Z
P(zquKm
=OA7$z[
ret O}Do4>02
iF+50d
N_.`5I;e
Temp:
@
|~D?&<\
r3Ih]|FK#
|qibO \_
dw 0 GlXzH1wZ
{y:+rh&
MS%h`Ypo
Add endp )#cGePA