这个SideKick是个好东东。 @g{
"
E6
wlJ_,wA
下面的程序不是我写的。 qW9|&GuZ$
<=lP6B
用汇编编写DOS下的内存驻留程序(1) .x&>H
b`'
;`*AN+
)yJjJ:re
Fc
Cxr@
) PtaX|U
uxBk7E%6
BehV
:M
绪言 N|; cG[W
GZo^0U,;
D UeT
0.1 内存驻留与中断 !&kOqc5:t<
/TdTo@
Wl{Vz
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 S<44{
oH
Wp ]u0w
6+>rf{5P7
内存驻留程序的常用形式有: vv3?ewr
y
f>o@Y]/l
`|4{|X*U.
>诸如Borland 的SideKick弹出式实用程序 6_7d1.wv9
Hmz[pTQ|87
q~Ud>{
>日历系统 se-}d.PwL
^gy(~u
tpS F[W
>网络服务器 q\\J9`Q$J
s<{c?4T
94+#6jd e
>通讯程序 K)n( U9#
+KZc"0?
5M3QRJ!
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) +oc}kv,h]
yTk9+ >
mcvTz, ;=
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. gS!M7xy
|( KM 8
Nt)
9-\T
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: Zn/1uWO
rW6LMkt72
%(i
(ZW "
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. W'[!4RQL
=1D*K%
IkupW|}rc
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. y]k`}&-~
m&2m' =(
#RcmO**
>以上各种的结合. {.ph)8
jhHb[je~{4
/dO&r'!:
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. ~96"^%D
`7NgQ*g.d/
w
^A0l.{
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. 5<61NnZ
DZvpt%q
7}x
KiHh:
手式计算中断向量的首址,可通过以下的公式来求得: d 1z
zx^)Qb/EL6
IMBqy -q
X号中断向量的首址=0000H:X*4 L^22,B
0
7Sokn?~i
Qx:+n`$/
当产生一个中断时,处理器都按顺序执行以下步骤: yy9Bd>
k,H4<")H
`g #\ Ws
>在堆栈上压入处理器的标志(相当于指令PUSHF). |KA8qQI]%
N24+P5
dJkTHmw
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). D/U o?,>8
0GB6.Ggft
V[%r5!83H
>关闭中断(CLI) 8<P.>u
BD#4=u
:]x)lP(3E
>从中断向量加载的CS和IP,执行中断处理程序. L\"$R":3{d
pz(clTOD:
~{
HA!C#
当执行完中断处理程序后,一般用IRET返回,它的作用是: b{sFN!
6rk/74gI,a
='s2S5#1
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). =w8*n2
CNzK-,
&" b0`&l
>同时恢复中断前的处理器标志(相当于指令POPF). wH<S0vl
9F3`hJZRy>
P9c1
NX\-
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. tZ(Wh
sbgRl%
A!NT 2YdHZ
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. Bk8U\Ut
b{(:'.
?p`}6s Q}
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. M 3^p,[9r#
0KEytm]
~_K
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. !0cfz5t
Od
"-w<'
WvR}c
s4w<X}O_
0.2 DOS的可重入性分析 r
/PsFv{8
pt=[XhxC(>
Ros5]5=dP
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. 'oo]oeJ-
X,~8) W
JjM^\LwKkL
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. k(Ow.nkb
Odagaca
h~dM*yo;
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: ;e-iiC]PI
4*'NpqC(_
7"M7N^
Add proc near z\fk?Tj<ro
-i9/1.Z
E_$ST3
cmp DS:word ptr [si],0 }(gXlF
S6cSeRmw
;DGp7f#9
je DonotAddTheValue WS;3a}u
KExfa4W 3{
a"~W1|JC"
add ax,DS:word ptr [si] 5e/%Tue.
z8A`B
VqI
$UKDXQF"
DonotAddTheValue: ow+NT
7%JXVP}A
h1,J<B@
ret 1W5YS +pf
$WdZAv\_S
Vb/J`
Add endp j&8U:Q,
`9@!"p
f
#*w$JH
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. +1e*>jE
E]Kd`&^}
S!rUdxO
mov ds,0100h ;ds=0100h 2-2'
c?%
d8|:)7PSt
CvlAn7r,@
mov si,0010h ;si=0010h yp8 .\.
)U8F6GIC&}
csYIC Lj
mov ax,0001h ;ax,=0001h MECR0S9
vhT9#) HI
fz<Y9h=
call Add rsrv1A=t?
!zD| @sX{
5o&L|7]
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine jk) U~KGcg
U;ev3
5-n N8qs
push ds ;Interrupted ZWYwVAo
1`b?nX
wjpkh~qo
push si wp$SO^?-
Il!iqDHz3
u K 8r
push ax !m78 /[LW
F/mD05{
0(teplo&P
mov ds,0200h ;ds=0200h WMrK8e'
d@`yRueWiV
RL($h4d9
mov si,0200h ;si=0020h 1298&C@
0\u_\%[
H3MT.Cpd
mov ax,0003h ;ax=0003h iPxSVH[
CKj3-rcF(
ZSxKk6n}J
call Add dBCg$Rud&
IhUuL0
n_iq85
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h 6Ba>l$/q
=$f
xK
;0@"1`
jne ;u, 5
2
\}Hk`n)Aq
}*
*^g:
add ax,0200h:word ptr [0020h] ;ax=0007h 2_U H, n
H,] D}r
UT"L5{c
ret ;Return gm4-w 9M[p
ZN^9w"A
@"Do8p!*(6
pop ax ;ax=0001h 3"%:S_[
g~N)~]0{
{d=y9Jb^
pop si ;si=0010h *_U
z**M
U edh4qa
_M{m6k(h
pop ds ;ds=0100h DAJh9I
&AA u:
2N `Vx3
iret ;Return to Add subroutine _Tev503
Ro?yCy:L'
(n#
jne "x&H*"
IgZX,4i=o
|)1"*`z
add ax,0100h:word ptr [0100h] ;ax= 0001h
%$Mvq&ZZ
N\mV+f3A@,
rY88
xh^
;0100h:0010h= 0002h q18dSu
}i?P(
Au
{_PV~8u
;---------------------------------------- 2uV=kq nO
:Ruj;j
IC7n;n9
;ax = 0003h iQ~cG[6
6]na#<
G| ^tqI
ret h1J-AfV
,1QU
,8@@r7
mov bx,ax jUdW o}/
|(Io(e
RDk{;VED{
而下面的子程序是不可重入的: BYP,}yzA
I5PaY.i
*9*6n\~aI
Add proc near 1 BVivEG
-H{c@hl
'Zk&AD ~
mov Temp,ax m&b!\"0
dc"Vc 3)
ptYQP^6S[
mov ax,DS:word ptr [si] d7P|
x
vBq2JJAl
7J##IH+z35
cmp ax,0 o
KX!{
luAhyEp
"!r7t4
je DonotTheValue K@%. T#
zaR~ fO
%5jxq9:K
add ax,Temp E9QNx62
C'kd>LAGu
/\h&t6B1
DonotTheValue: aZ#c_Q#gZ
lLoFM
0p:n'P
ret }4\>q$8'
sg{>-
KHM
#>[+6y]U!
Temp: Fpl<2eBg4
h?fv
:^vSi
SbrBlP:G
dw 0
`<q{8
Pqx=j_st
^hTq~ "
Add endp H?M8j] R-)