这个SideKick是个好东东。 2yZ/'}Mw
*W,tq(%tQ
下面的程序不是我写的。 &XAG|
#
LA &W@
用汇编编写DOS下的内存驻留程序(1) 0?OTa<c
x}v]JEIf[Q
0,$eiY)u$
M"# >?6{
=j#1HI=Fe
1AMxZ (e
~Sy/q]4ys*
绪言 l2H-E&'=
dd1CuOd6(1
uc;1{[5`1q
0.1 内存驻留与中断 eGcc' LBr;
gS{hfDpk,h
S. my" j
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 %+Hhe]J ld
JLgk?
vF
yl,S5A
内存驻留程序的常用形式有: Hl-!rP.?0
4)MKYhm
6[ }~m\cY
>诸如Borland 的SideKick弹出式实用程序 wJ#fmQXKJ5
!bs{/?
^ [FK<9
>日历系统 \AFoxi2h
s
zBlyT
(nd
Xz
>网络服务器 U8TH} 9Q
OBrbWXp@
XG_h\NIL
>通讯程序 qJV2x.!
;#-yyU
N
zrHWVD
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) ,@I_b
/zxLnT;
5
1eQfc{[g
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. -M=#U\D
CB V(H$d
aY`qb Jy
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: PP/EZ ^]b
K+2k}Hx6J
o[Ojl.r<
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. =AEl:SY+
l
Ozi|
Rdb[{Ruxb
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. {Yq"%n'0
]`@= ;w
9vIqGz-o
>以上各种的结合. lO^Ly27
}/)vOUcEd
^3~+| A98M
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. 2"0q9 Jg
}E[u" @}
;Q Y
UiR
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. 0_nY70B
Pn?Ujjv
*B<Ig^c
手式计算中断向量的首址,可通过以下的公式来求得: ":=\ci]e%
j}P
xq
'+?L/|'
X号中断向量的首址=0000H:X*4 >4I,9TO
GD*rTtDWn
aqL#g18
当产生一个中断时,处理器都按顺序执行以下步骤: JH3$G,:zM
mEK0ID\
4wLN#dpeEy
>在堆栈上压入处理器的标志(相当于指令PUSHF). hG1\
,q9nHZG^
w5/`_m!
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). 73/DOF
]rwHr;.
cD
^`dn%$
>关闭中断(CLI) PSCzeR
ZiR },F/
VycCuq&M
>从中断向量加载的CS和IP,执行中断处理程序. K|n%8hRy
h?t#ABsVK
x?10^~R
当执行完中断处理程序后,一般用IRET返回,它的作用是: RbOEXH*]
8w,+Y]X<P[
I^}q;L![\
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). "&$ [@c
q47>RWMh%
+Cs[]~
>同时恢复中断前的处理器标志(相当于指令POPF). 7Iz%Jty
WY>r9+A?W
1P8XVI'
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. #eRrVjbo
"gt-bo.,
Myj
5qh
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. ~rnbuIh
V$ 8go#5
`.oWmBey\
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. kHWW\?O
_xKu
EU}
l]g
/rs
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. ^Om0~)"q
x}^:Bs+j
rE->z
0`WjM2So
0.2 DOS的可重入性分析 y4N8B:j%
,K/l;M5I
6YErF|
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. e6G=Bq$
s&Bk@a8
" a&|{bv
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. RN,5>.w
/#<R
N@qP}/}8
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: F!k3/z
,\){-H/n
Q:L^DZkGV
Add proc near 5OJ8o>BF
f$7Xh~
/z=xEnU#
cmp DS:word ptr [si],0 Uz4!O
aNt+;M7g`
a:q>7V|%$
je DonotAddTheValue 8m prK`p
?"hrCEHV{9
dM-qd`
add ax,DS:word ptr [si] 3VI[*b
.Iu8bN(L`
iX&eQ{LB
DonotAddTheValue: f`;y
"ba
VL =
1 9[
n'?AZ4&z
ret \C{Dui)F
, 0hk)Vvr3
E=*82Y=B
Add endp >Bw<THx
:.VI*X:aQh
%w$\v"^_Y
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. kv!QO^;^Y
Ym% $!#
@Sr{6g*I
mov ds,0100h ;ds=0100h `j#zwgUs
~nP~6Q'wSH
biLNR"/E
mov si,0010h ;si=0010h
54lU~ "
Os90fR
Ux/|D_rlf
mov ax,0001h ;ax,=0001h o[
Je
XBr-UjQ
?IN'Dc9&%-
call Add @V\u<n
R^p'gQc$
*\-$.w)k
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine K'6NW:zp~
nE&`~
xmM!SY>
push ds ;Interrupted 6D\$K
Mzg
zOM
&g;&=<#I
push si ~vb yX
~M c'~:{O
f]_{4Olk
push ax 3BZa}Q_
?DGe}?pX
=~D QX\
mov ds,0200h ;ds=0200h -n:~m
p
^@V;`jsll
hR4\:s+[
mov si,0200h ;si=0020h
2@Nt6r
ia9=&Hy])
[
pe{,lp
mov ax,0003h ;ax=0003h &g.do
?
)X2/_3
@%^JB
call Add =K\xE"
?lPn{oB9"
%#jW
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h iJ&jg`"=F
o){\qhLp
p{vGc-zP.
jne \PzJ66DL!
;_K3/:
v 1.8]||^
add ax,0200h:word ptr [0020h] ;ax=0007h 1u~CNHm
F HK{cE
WR.>?IG2E
ret ;Return /Kd9UQU
W?:e4:Q
4@mK:v%
pop ax ;ax=0001h [yhK4A
De-hHY{>
K\trT!I
pop si ;si=0010h s+-V^{Ht
@zCp/fo3
QomihQnc
pop ds ;ds=0100h C>:,\=y%
7WMF8(j5
5(\H:g\z
iret ;Return to Add subroutine zk;'`@7
cr`NHl/XF
TOb(
jne '% if< /
mB5Sm|{
'8"nXuL-
add ax,0100h:word ptr [0100h] ;ax= 0001h "!B\c9q
+:_;K_h
?onEqH>
;0100h:0010h= 0002h ^$AJV%3wI
'>^!a!<G
<r1/& RW,
;---------------------------------------- =j"bLX6;
|muZv!,E
Q$*JkwPQ}
;ax = 0003h t?(fDWd|-
BO,xA -+
!{+a2wi
ret dFl8 'D
|V&E q>G
1xD?cA\vu
mov bx,ax .WVIdVO7
]:r(U5 #
AX] cM)w
而下面的子程序是不可重入的: 'Ul^V
jX;$g>P
6QYHPz
Add proc near LTTMxiq[*
ri1;i= W
S8,e`F
mov Temp,ax 4M)oA|1w
Vo;0i$
xFzaVjjP
mov ax,DS:word ptr [si] 98rO]
rg
m##_U9O
zN&m-nrw
cmp ax,0 JKF/z@Vbe\
@s|G18@
N[zR%(YS
je DonotTheValue YD,<]q%
)tv~N7
d6f T
add ax,Temp E*vh<C
bIXD(5y
b:Tv
Ta
DonotTheValue: ?dyt!>C
3(,c^F
'!"rE1e
ret 9 >"}||))
ILIv43QKM(
H1d2WNr[
Temp: 6ltV}Wt-
vhGX&
W) ?s''WE;
dw 0 emMk*l,
bcYGkvGbO
-7IRlP&
Add endp .3CQFbHF