这个SideKick是个好东东。 7
Lm9I
Z<vz%7w
下面的程序不是我写的。 xs"i_se
t ed:]
用汇编编写DOS下的内存驻留程序(1) ]es|%j 2
J6Ilg@}\
<XeDJ8
'
'm`O34h
2/?Zp=|j\
HWjJ.;k}a
~fXNj-'RW
绪言 7<j!qWm0
uKJ:)oyaCP
y3oq{Z>
0.1 内存驻留与中断 iuV4xyp
q<09]i
`cGks
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 \Id8X`,eD
jX7K-L
u+)!C*ho
内存驻留程序的常用形式有: O/~T+T%
KXPCkNIN!
=Vg~ VD
>诸如Borland 的SideKick弹出式实用程序 fQoAdw
*l_a=[<[
r^ ,_m,s'<
>日历系统 l#0zHBc
\RDN_Z
eb_.@.a
>网络服务器 tV++QC7@L
('z=/"(l
/uw@o9`~2-
>通讯程序 Z518J46o
M^kaik
.O-)m'
5
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) lS=YnMs6a
c~T{;
ZX_QnSNZ?
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. 6qZQ20h
Q7+WV`&
3p#UEH3
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: 7?fgcb3
7ZUN;mr
wkt4vE87
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. e9p/y8
gC
| R,dsBd
[MeivrJ+
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. 8{4'G$6
Il=6
t
RRO@r}A!y
>以上各种的结合.
eXl?f_9
>{^_]phlb
c^|8qvS$
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. cj>@Jx}]M
}u^bTR?3
Sm/8VSY
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. h[(YH ;Y
X_PzK'#m
0]>bNbLB"
手式计算中断向量的首址,可通过以下的公式来求得: |r@;ulO
e#}t
am
x.1=QF{!
X号中断向量的首址=0000H:X*4 "@x(2(Y&
d!I%AlV
:V9Q<B^
当产生一个中断时,处理器都按顺序执行以下步骤: WyV4p
]@U?hD
r6
S
>在堆栈上压入处理器的标志(相当于指令PUSHF). S]H[&o1o
qZ<n\Mt
xM_#FxJb
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). YdI6|o@vc
5 H
._Q
+:Zwo+\kSN
>关闭中断(CLI) NZGO8u
@5Z|e
SlsNtaNt
>从中断向量加载的CS和IP,执行中断处理程序. R&uPoY,f
$
DN.
HG7Qdw2+O
当执行完中断处理程序后,一般用IRET返回,它的作用是: cC8$ oCR?
~D5
-G?%$"
oCo~,~kTR
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS).
*RY
}e
0hS&4nW
RY5e%/bg~U
>同时恢复中断前的处理器标志(相当于指令POPF). 5zS%F: 3
4W>DW`{
&^ERaPynd
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. >Iij,J5i
2
[w9#6ly
(CQ! &Z8
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. dwn|1%D
<(E)M@2
{JWixbA
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. c<1$zQY!
i?_Q@uA~<:
[)`*k#.=
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. l<_v3/3
P~(&lu/;P
8mr fs%_
!MSa -
0.2 DOS的可重入性分析 i7H([b<_m
uNf'Zeo
n[/D>Pi
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. R5sE
Q| E
CX#d
(
%sfwv
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. puOM
tCI
B~o3Z
%Vo'\|
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: j Hq+/\
8z93ETv7`
2K~v`c*4
Add proc near oX6Cd:c-
$;g*s?F*
pll5m7[
cmp DS:word ptr [si],0 D u<P^CE
d^'_H>x
y95
#t
je DonotAddTheValue @.e4~qz\
Z@q1&}D!
IiKU=^~w
add ax,DS:word ptr [si] xEG:KSH
3@F U-k,i
H8HH) ^
DonotAddTheValue: }ll&EB
6~ET@"0uK
}5E H67
ret I>MLI=[Kg
<,Gjo]z
A7QT4h&6
Add endp p&}m')
['(qeS@5
O
K`=U5vG^
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. 7gtaI3
1mV
'
~W
K81FKV.
mov ds,0100h ;ds=0100h >u%B
n\G
D*L@I@
[
s\'t=}0q
mov si,0010h ;si=0010h uJ"#j
X
tdU'cc?M
X>dQK4!R
mov ax,0001h ;ax,=0001h ZV Ko$q:F
8Ogg(uS70'
, wk}[MF
call Add Ds=d~sN u
kU:Q&[/jzH
# wn>S<
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine 4g
Z R!J
z%fjG} z
G>dXK,f<B0
push ds ;Interrupted Q8TR@0d
tli*3YIw
"P5,p"k:)
push si Fkv284,LM
,ig`'U
`~axOp9N
push ax L{sFR^-G
+) 9=bB
,-])[
u
mov ds,0200h ;ds=0200h Njo.-k
ZrYRLg
u}'m7|)8
mov si,0200h ;si=0020h dsEvpa$?
BDN}`F[F
<a
CzB7x
mov ax,0003h ;ax=0003h xqT} 9,
*h?*RUQ
iLdUus!
call Add |$8N*7UD
axG%@5
=j_4!^
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h Xe}I;sKrB
B <Jxj
p+I`xyk
jne gC6Gm':c
<MxA;A
N]BH6 7<
add ax,0200h:word ptr [0020h] ;ax=0007h TGpdl`k\T
({4?RtYm
P EzT|uY
ret ;Return TPJuS)TU9
&~"N/o
Na\&}GSf^
pop ax ;ax=0001h 7WV"Wrl]
p@$92> '
"97sH_
,
pop si ;si=0010h MDpx@.A,
jxK
`ShW=
B
\V;{:
pop ds ;ds=0100h QIwO _[Q
-6q7ze{@
pE1uD4lLb
iret ;Return to Add subroutine !ggHLZRlz
8pm
Ww?
1\jj3Y'i'
jne H1evW
5=s|uuw/
lfoPFJ
Z
add ax,0100h:word ptr [0100h] ;ax= 0001h MNfc1I_#
0l(G7Ju
Mt4`~`6
;0100h:0010h= 0002h [CnoMN
T5[(vTp
Qz"@<qgQy
;---------------------------------------- r*7J#M /
ziAn9/sT
8v)Z/R-
;ax = 0003h
NR^Z#BU
2V @ pt
yrzyus
ret CS^|="Zs
j9
7c@
=+e;BYD#!
mov bx,ax nQw, /Lk
|$T?P*pI.
"t{D5{q|[k
而下面的子程序是不可重入的: &WbHM)_n
q|.0Ja
2 $Z4 >!
Add proc near q!d7
Ms{q
,|O|gh$s
(Q"s;g
mov Temp,ax [c>YKN2qa
?AQR\) P
Kt#X'!9/<
mov ax,DS:word ptr [si] ++kVq$9@y
eET1f8B=L
neWx-O
cmp ax,0 -OQ6;A"#
o>M&C
X+j$
t-FrF </0
je DonotTheValue J@Nq
$nthMx$
yX\~{%
add ax,Temp "jq F
1
RyvPP
CfLPs)\ACm
DonotTheValue: Kn+B):OY+
n%dh|j2u
3k+46Wp
ret e<{Ani0
f<DqA/$
%yy|B
Temp: Yu%ZwTvw
}e1]Ib!
g*U[?I"sC
dw 0 M/6q
^*
GQkI7C
_t7aOH
Add endp *=QWx[K|