这个SideKick是个好东东。 Fx/9T2%=
_2<|0lvh
下面的程序不是我写的。 ghx8dX}
eWhv X9
<
用汇编编写DOS下的内存驻留程序(1) {Ejv8UdA9
Q{Jz;6"
f>;5ZE4Zu
7?]gUrE
`Z{;
c
^>72<1U%
N?p9h{DG
绪言 mO?G[?*\
sYYg5vL9
u> %r(
0.1 内存驻留与中断 $xvEYK
d_QHm;}Cx
}^pnwo9vV
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 T=
ox;r
=9LC"eI&|
mRW(]OFIai
内存驻留程序的常用形式有: q(\$-Dk.Vv
3`5?Zgp
tV[?WA[xt
>诸如Borland 的SideKick弹出式实用程序 '_4u,
\SG
Ad+-/hxc
FJ!N)`[
>日历系统 `i9W
nPRt
U-Fr[1I6p
Ni(D[?mZ
>网络服务器 [t: =%&B
st:[|`
3
r%I *
>通讯程序 ePrbG4xv
S2*-Ulu
G
Vj:)w<],
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) OE}L})"
) Z0
]zhFFq`
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. <Lyz7R6
A&Ut:Oi
A
o{f n}
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: |/]bpG 'z
WvAl!^{`
YM1tP'4j@
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. F'C]OMBE
oYup*@t
c_kxjzA#
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. j &)|nK;}
4_F<jx,G
1;?b-FEq:
>以上各种的结合. ]W5s!T_
MztT/31S
tJ&S&[}
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. YzhZ%:8
!:c7I@
Oa$ew'
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. WLDt5R
VS%8f.7ep
gA`/t e
手式计算中断向量的首址,可通过以下的公式来求得: >Djv8 0
l9qq;hhGP,
MP w@O0QS
X号中断向量的首址=0000H:X*4 5\S)8j `8
q~;P^i<Y
{>5z~OV
当产生一个中断时,处理器都按顺序执行以下步骤: .Uh-Wi[
TAi
|]U!
~*L H[l>K
>在堆栈上压入处理器的标志(相当于指令PUSHF). E IsA2 f
r&o%n5B
f]J?-ks
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). oHxaa>C>
UDt.w82
kFw3'OZ,
>关闭中断(CLI) xPq3Sfg`A
:>Z0Kb}7
Nr|.]=K)5n
>从中断向量加载的CS和IP,执行中断处理程序. ~N>[7I"*
shYcfLJ
]\+bx=
当执行完中断处理程序后,一般用IRET返回,它的作用是: ?N,a {#w
[77]0V7
@H]g_yw [:
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). x|F6^d
8ftLYMX@
E$F)z
>同时恢复中断前的处理器标志(相当于指令POPF). [\ @!~F{
S]K^wj[
p!hewtb5
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. 85w
D<bN27
|b'tf:l
f2uog$Hk
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. (|(Y;%>-v
]^8:"Ky'
QI0ARdS
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. 8p-5.GU)<e
A}t.`FLP,j
ag:#82C
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. JBeC\ \QX
%vxd($Ti"
~
W52Mbf
j<"0ym)A
0.2 DOS的可重入性分析 \X
Nb 9-
uQ5NN*C=
K)_0ej~C
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. FT[wa-b
qWw@6VvoQ
`axNeqM
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. Tk|0
scjE^
|>j=#2
j;VYF
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: o:f=dBmoX
7M3q|7?
}1:jM_H)k
Add proc near feQ_dA q
v;JY;Uh|
TcauCL
cmp DS:word ptr [si],0 ` *$^rQS
$ daI++v`
Y
0&w;P
je DonotAddTheValue h+R}O9BD
q/m}+v]
RNl%n}
add ax,DS:word ptr [si] iMk`t:!;#"
L L9I:^
Pkc4=i,`A
DonotAddTheValue: v:JFUn}
_~HGMC)
s^L\hr
ret 5c'rnMW4+p
K 2LLuS!
azj<aaH
Add endp 3|P P+<o
<2}"Y(zwKl
?# ,\,
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. 4y>G6TD^
@U}fvdft
o~mY,7@a
mov ds,0100h ;ds=0100h 0EPF;
Xx
qe`W~a9x
;#~rd8Z52
mov si,0010h ;si=0010h g RSM~<
|n01T_Z)P
q'C'S#qqn
mov ax,0001h ;ax,=0001h P@k
;Lg"
b]hRmW
.zBSjh_=H
call Add :3Ty%W&&
1?E\2t&K
#uu wzE*M_
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine B 8C3LP}?
m4>v S
:d)@|SR1
push ds ;Interrupted @B7;
Qy0bp;V/
sBwkHsDD
push si G1$DVGo
~4XJ" d3L
TD!
QqLW
push ax <%qbU-
/3FC@?l
w4
d<`Z{"g NS
mov ds,0200h ;ds=0200h "%,zB_ng\<
r[EN`AxDb
@zsr.d6Q
mov si,0200h ;si=0020h e] **Z,Z
J@!Sf7k42
8QFY:.h&
mov ax,0003h ;ax=0003h *5*d8;@>
CDU^X$Q
`\e@O#,^yI
call Add k}F ;e_
2=["jP!B
;d?4phl-.
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h >
'Y] C\
X+P3a/T
T(J&v|FK
jne mfeyR
"84.qgYaG
lq.AQ
add ax,0200h:word ptr [0020h] ;ax=0007h _4[kg)#+
top3o{4
&&_W,id`
ret ;Return 34s:|w6y
MbYa6jrF
A' dt
WD
pop ax ;ax=0001h Vu~mi%UH
5OpK~f5
rh$%*l
pop si ;si=0010h WiPMvl8
(VC{#^2l
M~ynJ@q
pop ds ;ds=0100h \W/cC
'
Kc{fT^E
Pg*ZQE[ME8
iret ;Return to Add subroutine dXrv
+~w '?vNc
WXO@oZ!
jne (Pvch!
={#r/x
mR8&9]g&
add ax,0100h:word ptr [0100h] ;ax= 0001h oE-i`;\8
owmA]f
3o"~_l$z
;0100h:0010h= 0002h 9.vHnMcq
0fi+tc30
!. q*bY
;---------------------------------------- 'hU&$lgMF
R^%7
|
DX4
95<6*
;ax = 0003h Bk?M F6
@
B+
k9yA#
ret 9)l[$X
{{@3r5KGl
xV<NeU
mov bx,ax iCc@N|~
Rqvm%sAi
MFE~b
U(h
而下面的子程序是不可重入的: ro^Y$;G
6M612
q SCt=eQ
Add proc near 96MRnj*Y[
uysGOyi<u
(iBBdB
mov Temp,ax &W".fRH_O
}1X,~y]
3<'SnP3mY
mov ax,DS:word ptr [si] sNS!
/
RX7,z.9@'O
p
m3?
cmp ax,0 WlWBYnphZs
Dugr{Y/0
|`:Uww+3
je DonotTheValue ;rd!kFd#bq
0($MN]oZa
3YA !2
add ax,Temp )Cu"M#`
.i[Tp6'%,
iwrdZLE
DonotTheValue: TtkB
sx*(JM}Be
- Npl x
ret LB 2
2doW
L
LaoND6
pX6OhwkTK
Temp: [S3
X
0r:8ni%cL
=0x[Sa$&,
dw 0 <
8WS YZ
ph^qQDA
QFDjsd4
Add endp *K-,<hJ#L