这个SideKick是个好东东。
Zf~Z&"C) ^6(Nu|6\@ 下面的程序不是我写的。
`suEN@
^ of [email protected]O 用汇编编写DOS下的内存驻留程序(1)
TO~Z6NA0 ny{Yr
>:2 ' (1`iQ; NhYce> vhOX1' .~t.B!rVSB _)?59 绪言
U sS"WflB ,4tuWO)" %RS8zN 0.1 内存驻留与中断
eQqx0+-0c 0<C]9[l /I/gbmc) 内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。
s/0S]P]}f D
YFfq .>Fy ]Cqoh 内存驻留程序的常用形式有:
(B:+md\Q E\Et,l#|LY ~ '/Yp8( >诸如Borland 的SideKick弹出式实用程序
1Vy8TV3D {N2MskK ,`O.0e4pn >日历系统
4V9S~^v| dF<GuS;l5 TtKV5 >网络服务器
Qaeg3f3F3 ydm2'aV 7lH3)9G; >通讯程序
`8sC>)lrwu kMP3PS EAPjQA-B? >本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴)
/pS Y ~* $"[5
]{'J 6=o'.03\f >一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序.
`!A<XiAOmM nqMXE82 lrL:v~g 就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种:
1r LK1X l" P3lKS |`
,AAa >硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等.
"|KhqV=?v +zf[Im%E /\0g)B
;] >软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等.
iu+r=sp \]=''C=J (764-iv( >以上各种的结合.
MGU%"7i'} kt;uB
X3 'V#$PZx 从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明.
bs9X4n5 F2:nL`]b[ 6(0ME$ 在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表.
Cl>{vSN K*[`s'Ip- ]w;!x7bU( 手式计算中断向量的首址,可通过以下的公式来求得:
{\
62c;. P ")1_! |%l&H/ X号中断向量的首址=0000H:X*4
+l) [A{ &kp`1kv": "vL,c]D 当产生一个中断时,处理器都按顺序执行以下步骤:
a*(,ydF|L _(%;O:i =)mA.j}E2 >在堆栈上压入处理器的标志(相当于指令PUSHF).
yJn<S@)VT: <tx`#, ,z0~VS:g 8 >在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP).
'`nf7b( r(6$.
zx mx3p/p >关闭中断(CLI)
,\Uc/wR 64R~ $km /c:78@ >从中断向量加载的CS和IP,执行中断处理程序.
3F ]30 z<u*I@; BDiN*.w5 当执行完中断处理程序后,一般用IRET返回,它的作用是:
s5cY> D(&XmC[\Y >Xv
Fg >从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS).
NA;OT7X[ _my!YS5n u]uZc~T >同时恢复中断前的处理器标志(相当于指令POPF).
sf5 F$ ews{0
;\48Q; 中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断.
cy
@",z =jIP29+ +
ko-oZ7V 一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供.
;:A/WU.^ (29BS(|! |\3X7)^8D 如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明.
.TpM3b#r fIwG9cR o<8SiVC2 在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介.
jH~VjE> 3 =-XA2zJ }u?DK,R 1 ` ={** 0.2 DOS的可重入性分析
%
db V3v/hV: e` {F7rd: 一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行.
}LTy Xo T7q
E
2 uP NZ^lM 对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源.
3EO:Uk5< :F`-<x/ 8RaRXnJ 重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子:
fZka$
4 w6&p4Jw/H? R.P|gk Add proc near
4IGn,D^ yp
l`vJ]X "l[ c/q[ cmp DS:word ptr [si],0
(JdZl2A. `),ACkU>U g
?OC-zw je DonotAddTheValue
=GJ)4os &Fy})/F3v
YG K7b6
add ax,DS:word ptr [si]
h6~H5X h"ZR`?h o/4U`U)Q0v DonotAddTheValue:
bBg=X}9 !}I+)@~\w |kK_B
:K ret
!si}m~K!_ ]Mb
:zs<r nv'YtmR Add endp
Tx:S{n7&
ow2tfylV B`mTp01 上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种.
!>,XK!) teX)!N [ ,%<ICusZ mov ds,0100h ;ds=0100h
/w
"h'u :[d*
/0z#0gNp mov si,0010h ;si=0010h
ffI
z>Of: &<
oJw TC #,B+&SK{ mov ax,0001h ;ax,=0001h
d8ck].m= |!hN!j*) !Y^3% B% call Add
/ht-]Js$G %R
m`+ '1vm]+oM
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine
uRCZGg&V?# N.F//n 0f9*=c push ds ;Interrupted
?M9?GodbP. RcpKv;= iB g(QT"O!dY push si
w
2
1g& 6BH
P#B2j dh
K<5E push ax
oxZXY]$y /5N`Euw HA`qU
mov ds,0200h ;ds=0200h
s~>0<3{5 G/4~_\YMq :F`"CR^, mov si,0200h ;si=0020h
#M@Ki1
`Bzj
DI:a D*}_L
mov ax,0003h ;ax=0003h
\$W\[s
4I ;GV~MH-F lOEB ,/P
call Add
Mem1X rBH GD@|XwK){ Ju"K" cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h
P&sYS<9q T%O2=h\} E xua
E\*m jne
2#)z%K6T Gy6PS{yY6t 'y%*W:O add ax,0200h:word ptr [0020h] ;ax=0007h
t
.-%@,s " 3tk"#.# 5fY7[{2 ret ;Return
,-`A6ehg :R1F\FT* fjh,e pop ax ;ax=0001h
yt[*4gF4 nxhn|v cH6<'W{* pop si ;si=0010h
jUGk=/*]e a?1Ml>R6P * _@t$W pop ds ;ds=0100h
X|4_}b> x p-f"4vH 0 HPqoen$ iret ;Return to Add subroutine
"1z#6vw
5a `EWQ>m+ T
)!kJ;vc jne
Lhmb=
@ Pq3m(+gf w^E$R add ax,0100h:word ptr [0100h] ;ax= 0001h
nA#N ,^Rr k7)<3f3&S. RxO!h8 ;0100h:0010h= 0002h
A;Av0@w 7u<C&Z/ )QAS 7w#k ;----------------------------------------
oef] LXS)(-& 1<F6{?,z ;ax = 0003h
TrR=3_;.7 -jk-ve ZW%;"5uVm) ret
dM)x|b3z ,d@FO|G#pt BI6]{ ZC" mov bx,ax
^8V8,C) H> Q
X?>j 2g
HRfTF 而下面的子程序是不可重入的:
|Sr
`h='FJ/! :CGh$d] + Add proc near
cI (} pSdtAv s_
%LU:WC mov Temp,ax
XCj8QM.o sUz,F8G iyTKy+3A mov ax,DS:word ptr [si]
Wa<SYJ 9o+e3TXp# t~M0_TnXlP cmp ax,0
N7UGgn= o]TKL
'gW o2R&s@%0@B je DonotTheValue
.f-s+J&ED wo5fGQJ P2fiK add ax,Temp
e)f!2'LL i;fU],aK! bBY7^k DonotTheValue:
J;GYo|8 ub9,Wd"^ 2Dw}o;1' ret
")i_{C,b^ :=?od
0]W (d*~Qpi{7 Temp:
8;$zD]{D1 7bY N 1 Szv4 dw 0
{y`n_ @ n^2UJ #b>D^=NV>) Add endp
,pIaYU{D