这个SideKick是个好东东。 <0!)}O
i8i~b8r]
下面的程序不是我写的。 kJK:1;CM?.
w i=&W
用汇编编写DOS下的内存驻留程序(1) _ Y8jl,J
]B=2r^fn
d6+{^v$#
l$DQkbOj
]5sU =\
[E6ZmMB&
y7/=-~
绪言 ?
H7?>ZE
#5=!ew
p$1y8Zbor
0.1 内存驻留与中断 dO|n[/qL0
4$MV]ldUI
W}rL HAaDh
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 idSc#n22
Wk-jaz
yYn7y1B
内存驻留程序的常用形式有: Rn5{s3?F~2
K
}TSwY
t>%+[7?6
>诸如Borland 的SideKick弹出式实用程序 Y JMaIFt
qJYEsI2M
X}G3>HcP
>日历系统 5%;=(Oig
r(DW,xoK0
|7@@~|A
>网络服务器 XG;Dj<Dm
;noZmPa
[28Vf"#]
>通讯程序 KxUO=v<u
J[jzkzSu`
],xvhfZ"dn
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) GRj#1OqL
DE!P[$J
}CB9H$FkCY
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. -PLh|
=q?s B]n
j5V{,lf
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: tde&w=ec
[6cf$FS9
EJaGz\\
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. PIZK*Lop
z-G*:DfgH
S/)yi
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. #s3R4@{
MKZq*
9M Ug/
>以上各种的结合. A? T25<}
/\d@A B^5I
[['
(,,r
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. FN"Ye*d
9
gWqs'
meArS*d
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. 6<
{XwmM
'NSfGC%7R
]/c!;z
手式计算中断向量的首址,可通过以下的公式来求得: [kL`'yi
hL}AgY@
_8&a%?R@W
X号中断向量的首址=0000H:X*4 #kRt\Fzq
iNv"!'|
uE-|]QQo
当产生一个中断时,处理器都按顺序执行以下步骤: f/UIpswrZ'
84f^==Y
I/Q~rV
t
>在堆栈上压入处理器的标志(相当于指令PUSHF). IUSV\X9
^+rI=c 0
Bf8[(oc~
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). N%fDgK
8;5@5Au
Uo=_=.GQ
>关闭中断(CLI) VkZ3 Q7d
LQXMGgp
-AZ\u\xCB
>从中断向量加载的CS和IP,执行中断处理程序. )bl^:C
%1z`/B
CQ/ps,~M
当执行完中断处理程序后,一般用IRET返回,它的作用是: xY<*:&
@\|Fd)
0q_?<v_1
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). X^7n/|%*.
Da&Brm
:[!b";pR
>同时恢复中断前的处理器标志(相当于指令POPF). VX]Ud\(
iKA}??5e
k4`(7Z
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. _<6B.{$\7m
"T1A$DKw+R
a&%v ^r[
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. =}
flmUv~
OXD*ZKi8
KkyZd9
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. Bz4;R9_%I
%hN7K
W WN2
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. rB}2F*eT
]qO*(m:}o
}Wz[ox 9b
[,Fu2j]
0.2 DOS的可重入性分析 IZOO>-g'f
Y?xc#'
buA/G-<e
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. eoxEnCU
AGK{t+`
qX:YI3:,@
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. dr^MW?{a\
\fJ
_,
yt1dYF0Xq
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: yyc4'j+
E3QyiW
oN&U@N/>aU
Add proc near `{ ` W-C
Hd
?#^X
cd]def[d
cmp DS:word ptr [si],0 jYE
?wc+FT
*Z2#U?_
^|ul3_'?
je DonotAddTheValue iE,/x^&,&
\vF*n Z5/
@
GXi{9
add ax,DS:word ptr [si] ~%QI#s?|
)W |_f
UYvdzCUh
DonotAddTheValue: #y*p7~|@
Hl=M{)q@
SshjUNx
ret _E8doV
LZz]4Mf
LjPpnjU
Add endp uy8mhB+]
r;SOAucX
'Oa(]Br[
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. '.IR|~ Y
8om)A0S
FC#t}4as
mov ds,0100h ;ds=0100h y@9ifFr
Oz-@e%8L
e7M6|6nb
mov si,0010h ;si=0010h Nc:0opPM
}E#1Z\)
qv)%)n
mov ax,0001h ;ax,=0001h $\q}A:
b{a\j%
|C}= 1
call Add 5~{s-Ms
_l=X?/
wPl9%
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine F~wqt7*
A O3MlK9t
*nlDN4Y[
push ds ;Interrupted $aDkZj
`Tc"a_p9t
{) Pg N
push si 9"f
-~ H?R
.wf$]oQQ
push ax Oj#/R?%,X
9F2MCqvcm
51Q
~/
mov ds,0200h ;ds=0200h ]:svR@E
m4,inA:o
g]jCR*]
mov si,0200h ;si=0020h z,c=."<z
k FCdGl
A@)ou0[n@
mov ax,0003h ;ax=0003h f
J+
\
k &ZA
W4$F\y
call Add wG
X\ub#!
U[|o!2$
ub]"b[j\1
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h Tzr'3m_
!+_X q$9_
2 sK\.yS
jne lD6PKZ\RIj
aPm2\Sq$
E{]PfUfFY
add ax,0200h:word ptr [0020h] ;ax=0007h PZk"!I<oN
Jp-6]uW
5E0dX3-
ret ;Return BQL](Y"
X{8g2](z.
%s ">:
pop ax ;ax=0001h
495A\8#
}TRVCF1
#PQhgli
pop si ;si=0010h ?6 //'bO:%
b]
~
z9JZV`dNgz
pop ds ;ds=0100h E^? 3P'%^
S^_F0</U,
X1o
=rT
iret ;Return to Add subroutine bFsJqA.A
=O>E>Q
>j)y7DSE
jne RKb (
d'[]
`gz/?q
add ax,0100h:word ptr [0100h] ;ax= 0001h +u
;RF
Y^
V=)' CCi{
?JMy
;0100h:0010h= 0002h TnJJ& "~3b
&VT O9d
2q ~y\fe
;---------------------------------------- #]z_pp:
k;Ask#rs
/7igPNhx
;ax = 0003h M?QX'fia
Ir6g"kwCKq
[U_
ret l(d3N4iz
+Sak_*fq
VF:95F;@
mov bx,ax Yz? 8n
+ I4s0
\
-CL}Z}S
而下面的子程序是不可重入的: TV~S#yg+H
F?XiP.`DR
La
r9}nx0
Add proc near 0N):8`dY
a]@BS6
I8VCR8q
mov Temp,ax f}cCnJK
6-QcHJ>m6U
[ps5
mov ax,DS:word ptr [si] 6xoCB/]
4rUOk"li
o ^""=Z
cmp ax,0 }NKnV3G/Z
0gH;y+\=*
]K|td)1X
je DonotTheValue DeTLh($\
#sM*<
2vj
OPC8fX5.
add ax,Temp yny1i9
y
,tak{["
Bb.U4#
DonotTheValue: *{dMo,.eI
4DsHUc6
AtNF&=Op
ret t(p}0}Pp
dWiX_&g
w]O,xO
Temp: U &RZx&W
X9;51JV
}s:~E2?In
dw 0 <v3pI!)x
> *soc!# Y
PLRMW2
Add endp zo:NE00