这个SideKick是个好东东。 ,VI2dNst\
`Ps&N^[
下面的程序不是我写的。 /;
w(1)B
#mFIZMTRd
用汇编编写DOS下的内存驻留程序(1) c1Skt
fC&hi6
EjrK.|I0
,XU<2jv]
:wtK'ld
R10R,*6>
Dc2H<=];
绪言 iU+O(vi
nH_M#
y2cYRHN[X}
0.1 内存驻留与中断 F P3{Rp
Dr)B0]KG
XU_gvz
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 0l;TZf=H
h:xvnyaI
^
?}-x
内存驻留程序的常用形式有: kZ$2Uss
0-6rIdDTM
I|(r1.[K
>诸如Borland 的SideKick弹出式实用程序 >4
VN1^
Fsz;T;
pC^d-Ii
>日历系统 Qu|H_<8g
MR}=tO
K|]/BjB
/
>网络服务器 I;FHjnn(
\8g'v@$wG
n&1q*
>通讯程序 u^, eHO
}Y:V&4DW
:<hM@>eFn
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) 7v't#
=
FN\*x:g
{\hjKP
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. \ ,D>zF
h/k00hD60
uVN2}3!)Y
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: sFt"2TVr3
GCZx-zD~>
W[/Txc0$
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. S"HdjEF7\
>P@g].Q-
t^
Ge "
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. lha)4d
gamE^Ee
LGB}:;$AL
>以上各种的结合. ? fW['%
>cJix
1
-!q^/ux
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. DaP,3>M
8
kvF~d
;
!y+uQ_IS@
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. 42M_ %l_
52ExRG S
>jz9o9?8
手式计算中断向量的首址,可通过以下的公式来求得: F/V-@SF
>e^bq/'
w$iQ,--
X号中断向量的首址=0000H:X*4 @CMEmgk~
|yS %
xIA] 5@;a
当产生一个中断时,处理器都按顺序执行以下步骤: >
9.%hSy
HA$Xg
j
'hR0JXy
>在堆栈上压入处理器的标志(相当于指令PUSHF). V/`vX;%
F_G .$aCc
KT[ZOtu
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). (1
(~r"4I
$7" Y/9Y
Hsn'"
>关闭中断(CLI) qF\w#nG
Wn2'uZ5If
qA0PGo
>从中断向量加载的CS和IP,执行中断处理程序. bbM^J
.J<t]
sKCYGt$
当执行完中断处理程序后,一般用IRET返回,它的作用是: rU+3~|m
9HB+4q[
0 30LT$&!
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). =WT&unw}
u8.F_'` z
bFjH*~
P
>同时恢复中断前的处理器标志(相当于指令POPF). fqjBor}
'Fy"|M;2
1oe,>\\
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. CFC15/yU
ZLP/&`>8
X!_&%^L'
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. F/ x2}'
ClG\Kpirh
DL`8qJ'mJs
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. JR8|!Of@B
A3)"+`&PUl
X$
e*s\4
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. S/"G=^~
,p{naT%R
i-PK59VZ8f
]~2iducB,
0.2 DOS的可重入性分析 ,~ q:rh+
EQN)y27poW
[Do^EJ
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. 'Lq+ONX5
=p^$>o
]VL} eHZ
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. {0~\ T[qm
?Z2`8]-E
4%2APvLW
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: ;4l8Qg
7
!c`&L_ "!
Idb*,l|<
Add proc near ~UJ.A<>Fh
Q3Pu<j}Y
~7 `,}) d
cmp DS:word ptr [si],0 ,OWk[0/
p#).;\M
O}>@G
je DonotAddTheValue "iTjiH)Q(
v4<W57oH
D&i\dgbK
add ax,DS:word ptr [si] 4GbfA
.u
!B 4z U:d
LN~mKoW
DonotAddTheValue: a*-9n-U@[k
)X?oBNsj
.W^B(y(tA
ret !KMl'kswe:
f"RC(("6W
}f;WYz 5
Add endp /jNvHo^B
/5)*epF+
T%%
0W J
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. P0y DL:X[
~Oa$rqu%m
6@TU9AZS`
mov ds,0100h ;ds=0100h 3_<l`6^Ns/
<o/!M6^:
8tQ;N'
mov si,0010h ;si=0010h !NH(EWER
"I66@d?
-'Ay(h
mov ax,0001h ;ax,=0001h cI P.5)Ca
\_WR:?l
u$yXuFj/
call Add EjL]#,QR
PChe w3
f";pfu_FZ
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine .u>[m.
Vm|KL3}NRv
H1f='k]SZ
push ds ;Interrupted iLch3[p%
|Fe[RGi+8
)7 q"l3e"u
push si <Y."()}GeH
>MJ#|vO
k:I,$"y4
push ax /cb`%"Z
Pr1qX5> =
+}O -WX?
mov ds,0200h ;ds=0200h
y{/7z}d
ulxfxfd
}[Z'Sg]s
mov si,0200h ;si=0020h M^[;{p2uZ
-=nk,cYn
OKAU*}_
mov ax,0003h ;ax=0003h ] L97k(:Ib
&n
DXn|
dzEi^*
(8
call Add <Xl#}6II
L/Q[N^ (^
VE-l6@`
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h Asv]2> x
`Jk0jj6Z
Z/%FQ
jne ?<${?L>
;+<IWDo
Gsv<Rjj:
add ax,0200h:word ptr [0020h] ;ax=0007h )O" E#%
A+="0{P
kL%ot<rt)w
ret ;Return 5]>*0#C
S
9Q=VRH:
]o8]b7-
pop ax ;ax=0001h ._^}M<o L
?OLd
}8y
][wb4$2
pop si ;si=0010h T/\RViG3
5afD;0D5TI
rw,Ylr:3
pop ds ;ds=0100h /1MmOB
Xd=KBB[r?
^#d\HI
iret ;Return to Add subroutine RqgN<&g?
[02rs@c>
*mzi ?3
jne b%0p<*:a/
/kY9z~l
q)i %*IY
add ax,0100h:word ptr [0100h] ;ax= 0001h sSZ)C|Q
UB.1xcI
6LBdTnzUd
;0100h:0010h= 0002h `wXK&R<`
5X20/+aT
wkM1tKhy/
;---------------------------------------- =}0Uw4ub(u
}3^
m>i*8
K f/[Edn
;ax = 0003h I)rO|
sSh{.XuB+3
4T31<wk
ret !\X9$4po@
r|EN 5
(da`aRVDp
mov bx,ax qtExd~E
^K;k4oK
1ZI1+TDH
而下面的子程序是不可重入的: bZNqv-5 4h
ZU73UL
G9f6'5 O
Add proc near Z#Mm4(KNh
sq!$+
=1-X
Fp/{L
mov Temp,ax 5Jbwl$mZ
rS{}[$Zpl
3]l)uoNt/
mov ax,DS:word ptr [si] #73pryXV
D`T;j[SsS#
[3jJQ3O,
cmp ax,0 SI
=$s>1
U?#wWbE1
g}NO$?ndg
je DonotTheValue wAKHD*M)
|Y>Jf~SN
"E(i<
add ax,Temp /?eVWCR
I.n,TJoz4J
Wd:pqhLh
DonotTheValue: Y~AjcqS
{4D`VfX_
%rylmioW>
ret zY*9M3(X
SXk.7bMV6
_ocCt XI9
Temp: j|t=%*
Kcm+%p^
UJL2IF-x
dw 0 rP:g
`?*V
4yxQq7
m,
:j]1wp+
Add endp ,WRm{v0f^