这个SideKick是个好东东。 d&}pgb-Md
>.DF"]XM
下面的程序不是我写的。 [D*J[?yt
0Y2\n-`z
用汇编编写DOS下的内存驻留程序(1) k1ipvKxp:8
eV[`P&j_C
^=eq .(>
JP{UgcaF
Wmz q
9
9Ba{qj
q+YuVQ-fx
绪言 cZNi~
E
S#rs="
0lX)Cl
0.1 内存驻留与中断 Ad dGB^7yl
pyUNRqp
%v5)s(Yu
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 k_,MoDz
1 L+=|*:
*)MX%`Z}
内存驻留程序的常用形式有: 4`'8fe/
"
>Y7r\
Um]p&phVL
>诸如Borland 的SideKick弹出式实用程序 j y7
6-mmi7If
O
a$w},=
`E
>日历系统 6OfdD.y
)>(L{y|uYX
z=ML(1c=
>网络服务器 u9TzZ
-Qg
2qN2{
lp,\]]
>通讯程序 ( MB`hk-d
Cw
1 9y
Hu<p?mF#
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) `d75@0:
7IA3q{P
285_|!.Y
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. m! rwG(
+O)]^"TG
mgy"|\]
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: \n[
392
Q Oz9\,C
DZ^=*.
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. <A)+|Y"^h6
c]6V"Bo}A
` *>V6B3
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. 'Pf_5q
K1:a]aU?Iu
?QGmoQ)
>以上各种的结合. Nc{]zWL9
xKY$L*
d!`lsh@tF
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. wb]*u7G
t/
Qm
$(
Y.q>EUSH
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. Hl4\M]]/&
o:_^gJ+|
7N>oY$&)
手式计算中断向量的首址,可通过以下的公式来求得: M(qxq(#{U
vT?Q^PTO
{I`B[,*
X号中断向量的首址=0000H:X*4 CXTt(-FT
}c}
( 5
*i`v~>
当产生一个中断时,处理器都按顺序执行以下步骤: /@Ez" ?V2
]\OWZ{T'j
+AB6lv
>在堆栈上压入处理器的标志(相当于指令PUSHF). b& V`<'{
3@&bxYXm
L'>s(CR
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). p ss6Oz8
|</"N-#S
=K .r
>关闭中断(CLI) -<_7\09
Y5HfN[u^7
9u?(^(.
>从中断向量加载的CS和IP,执行中断处理程序. 3=Z<wD s
mKV'jm0
Am=wEu[b
当执行完中断处理程序后,一般用IRET返回,它的作用是: :v`o6x8
9ftN
8Svw
PfyRZ[3)c
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). SC'BmR"ox
mV<i JZh
"ml?7Xl,n
>同时恢复中断前的处理器标志(相当于指令POPF). DMB"Y,
2A*/C7
Xq|nJ|h
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. 5|{)Z]M%9
(B&h;U$HAH
O:1DOUYXs
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. UV4u.7y
Y
Zibi
h}avX*Lx_
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. M:_!w[NiLp
[Gh"ojt]w
+O'vj
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. oAY_sg+
Qu`n&
CD} Ns
VMx%1^/(
0.2 DOS的可重入性分析 :y\09)CJK
gC`)]*'tE
Gfv(w=rr?
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. I0DM=V>;
^\:yf.k
\k;U}Te<
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. Y~az!8j;Z
/KAlK5<
&Cq{
_M
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: U h.Sc:trA
_ENuwBYW-
;+
G9-
Add proc near yLW/ -%I#u
s;J\Kc?"|
e&2wdH&
cmp DS:word ptr [si],0 va5FxF*%
v
h
&GIb
4b4QbJ$
je DonotAddTheValue 9RxO7K
CN/IH
DF'8GF&Rp
add ax,DS:word ptr [si] ;W0]66&
;`kWpM;
Vu[:A
DonotAddTheValue: H>?F8R_iq
84'?um
_9
NVE|c;
ret 71O3O7
1~'_K9eE
~Eq \DK
Add endp %fv)7 CRM
('t kZt%8
{rC~P
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. `@|w>8bMz{
QsOhz
kg3ppt
mov ds,0100h ;ds=0100h >Rt9xP
0 O~p7D
,-@5NY1q
mov si,0010h ;si=0010h )Pli})
:M j_2
&3Tx@XhO
mov ax,0001h ;ax,=0001h }~Q5Y3]#~
8%[HYgd5)
noC?k }M
call Add _UkmYZ/
kJk xx*:u
gLIT;BK
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine W/r^ugDV
Jf)3< ~G
G
AQ
'Ti1!
push ds ;Interrupted &!jq!u$(
t+Z`n(>
oEu>}JD
push si 6^;^rUlm
1TjZ#yP%1
dv7<AJ
push ax <qhBc:kc
bD<qNqX$
s*Ih_Ag=:
mov ds,0200h ;ds=0200h yG&2UqX
,- '4L9
r~8;kcu7
mov si,0200h ;si=0020h C0fmmI0z~
[9V]
On
5lTD]d
mov ax,0003h ;ax=0003h w(BH247`
#dc1pfL!y{
.$Bwb/a
call Add gDCOLDM
`5'2Hg
+
o9Sn*p-.
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h m_*R.a
&aPl`"j
ioV_oR9I
jne MdC<4^|
dn,g Z"<
xhw-2dl*H
add ax,0200h:word ptr [0020h] ;ax=0007h `tE^jqrke5
,+._;[k
Fk1.iRVzi
ret ;Return bU`=*
>|3a
9S
2yKz-"E
pop ax ;ax=0001h )`8pd 7<.
5j{Np,K
D|_V<'
pop si ;si=0010h 6GYtY>
NP/>H9Q2%
S &JJIFftO
pop ds ;ds=0100h %6ub3PLw8
n|i"S`
gLQ #4H
iret ;Return to Add subroutine \DA$6w\\
++8_fgM
>fzwFNdo
jne F98i*K`"
1$ML #5+,
Y)XvlfJ,h?
add ax,0100h:word ptr [0100h] ;ax= 0001h `.=sTp2rbc
Pl+xH%U+?
_8><| 3d
;0100h:0010h= 0002h ~ y;y(4<
)"`!AerJ
n.hElgkUOr
;---------------------------------------- R8&|+ya
kIvvEh<L=
\M(*=5
;ax = 0003h nrpI5t.b
+l?; )
9vI]LfP
ret *7" L
]6
0mexF@
*Oo &}oAj
mov bx,ax #Qbl=o4
S#8>ZwQ
NQ9Ojj{#
而下面的子程序是不可重入的: &Un6ay
:gI.l1
RY=1H
Add proc near :Q@)*kQH
-2i\G .,J
&|5GB3H=
mov Temp,ax Lw*]EG|?
ksW
SMxm
u+D[_yd^
mov ax,DS:word ptr [si] a<m-V&4x
q0O&UE)6Y
}!)F9r@\
cmp ax,0
/\=MBUN
ZA\/{Fw
[VSU"AJY
je DonotTheValue 4nkE IZ
R Fko>d
R$m`Z+/@
add ax,Temp _+w/
pS`M
$/_qE
&mE?y%
DonotTheValue: "tu*YNP\Q
.Q>!B?)
&~-~5B|3"
ret ]Kdet"+
^#e~g/
Vq ^]s$'
Temp: V 0{tap}
rt4Z
;
Yck~xt&]
dw 0 lBA +zZ
g4&jo_3:p
9z ?7{2C
Add endp wJG$c-(\0