这个SideKick是个好东东。
r5s$#,O/&Q ;,&$ob*/ 下面的程序不是我写的。
h%=>iQ%enc '#*5jn]CqB 用汇编编写DOS下的内存驻留程序(1)
HLruZyN4 BKJwM'~ )=9EShz! aP`[O]8j %~{G*%: C)H1<Br7 OS{j5o 绪言
",Ge:\TR= $LXz
Q>w9 4k6,pt" 0.1 内存驻留与中断
4Yx\U ;zpSyyp@ cs\/6gSCo 内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。
QRw/d}8l _?m%i]~o FCp\w1+ 内存驻留程序的常用形式有:
wF\5 X '*d);{D8 m Bc2x8g) >诸如Borland 的SideKick弹出式实用程序
}
N$soaUs xlHC?d0} B098/`r >日历系统
t Urwg
O9/7?"l" D,( "3zx >网络服务器
15)y]N={^ ,x]xtg? Wf>P[6 >通讯程序
"'9[c"Iz 2c u?2_, P_y8[Y]? >本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴)
`9>1 w d i|/EA7 \~4IOu >一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序.
(Z)F6sZ`8 4\rw JD< vi8)U]6 就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种:
C%LXGMt <<iwJ
U%: 2sXNVo8`w" >硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等.
@TqqF:c7 }z|@X KA# E4;@P']` >软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等.
-0G/a&ss 0DQ\akh 7w
A.:$ >以上各种的结合.
0^G5 zQlj 3{/Y&/\"'^ O)EA2`)E 从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明.
K:_5#!*^98 3mCf>qj73 4],*y`& g 在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表.
q2U8]V U)
.^ o3 =VFPZ
手式计算中断向量的首址,可通过以下的公式来求得:
)_-EeH ] l@Mo7|w *$6dN x X号中断向量的首址=0000H:X*4
gOSFvH8FU )^q7s&p/ D>>?8a 当产生一个中断时,处理器都按顺序执行以下步骤:
*?<ygzX 1SY`V?cu iQ7S*s+l5O >在堆栈上压入处理器的标志(相当于指令PUSHF).
jSKhWxL;' n72+X G Ch]5\ >在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP).
1{0 L~
J =j6rD by0@G"AE+ >关闭中断(CLI)
5p]Cwj<u ?ZS/`P0}[ mR|;}u;d >从中断向量加载的CS和IP,执行中断处理程序.
M7x*LiKc2 -w3KBlo %fH&UFby 当执行完中断处理程序后,一般用IRET返回,它的作用是:
Q.zE}ZS %+F%C=GqI NKX62 ZC
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS).
+jifbf- +yO^,{8SE 'ai3f >同时恢复中断前的处理器标志(相当于指令POPF).
'G>gNq BJ,D1E [.[|rnil 中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断.
O% }EpIP_ k __MYb >anq1Kf 一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供.
("!P_Q# "IE*MmsEz ?mME^?x
Mu 如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明.
,
fR /C P
r_$%x9D O_bgrXg6x 在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介.
J 6%CF2 G-#]|) *F)+- BB !YZ$WiPl 0.2 DOS的可重入性分析
:rcohzfa 5 52U~t 6{8dv9tK 一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行.
)u67=0s2i+ =j&qat TTQ(\l4
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源.
gfU@`A_N" *ke9/hO1i =e j'5m($3 重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子:
vXUq[,8yf 8-.jf (t%+Z"j Add proc near
Zy+EI
x b>_eD-
3~5%6` cmp DS:word ptr [si],0
9s9_a4t5 e4rhB"qQdn |OarE2 je DonotAddTheValue
tY>_+)oi K H&o`U(} M tD{/.D> add ax,DS:word ptr [si]
x } X1
O) <{"Jy)Uf Q}(D^rGP3 DonotAddTheValue:
5U[
bn=n C#3K.0a wrJ:jTh ret
1:Dm,d;
8RE" xJMff PS\n0 Add endp
%'vLkjI. Ce~
a(J|" fHc/5uYW 上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种.
u
^}R]:n =E~)svl6g rfwX:R6,g mov ds,0100h ;ds=0100h
4w<4\zT_U} hY5tBL TLWU7aj&! mov si,0010h ;si=0010h
6M-Y`T`J QgB%\mO= 1O@y
>cV mov ax,0001h ;ax,=0001h
~
IIlCmMl, r{1xjAT f0Zn31c^ call Add
~P@6fK/M bxFDB^ ?x-:JME0 cmp 0100h:word ptr [0010h],0 ;Call Add subroutine
@9ndr$t *$/!.e [email protected] push ds ;Interrupted
n `Ry!
V
'
e_gH iLR^ V!
push si
zmdu\:_X9 Pko2fJt1 ,
lUr[xzV push ax
_a[)hu8q. xTV3U9 v hO H
DXc" mov ds,0200h ;ds=0200h
){S/h<4m s ;N PY Q/u1$&1 mov si,0200h ;si=0020h
j 5{"j VHlo}Ek<# 3g''j7 mov ax,0003h ;ax=0003h
XaH%i~}3 ?V>{3 _`L
QnRp( call Add
8*[Q{:'. S(MVL!Lm
rV6SN. cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h
(Ymj
1 ^q~NYTK #OE]'k
Ss jne
P{tH4V23T KH_~DZU*5 rh
+2
7" add ax,0200h:word ptr [0020h] ;ax=0007h
^+b ??K C;BC@OE jJU9~5i? ret ;Return
9X%H$>s [L4s.l_# SIr^\iiOB pop ax ;ax=0001h
JrhDqyk* `Ir{ax&H.e Y-
vLEIX= pop si ;si=0010h
b8$(j2B~ *!p#1fE L-V+ `![{ pop ds ;ds=0100h
o n+:{ad Th%2pwvER ,- FC iret ;Return to Add subroutine
E>2~cC* q\q8xF~[p X@cO`
P jne
<-avC/M$d 8&2W^f5 .e|VW) add ax,0100h:word ptr [0100h] ;ax= 0001h
v5Qp[O_ z:a%kZQ!0 rM5{R}+; ;0100h:0010h= 0002h
W]l&mr W:V:Ej7 h pipO,n ;----------------------------------------
D @bnm
s O77bm,E [\ALT8vC?m ;ax = 0003h
i{.%4tA4 )e6)~3[^ *~H\#N|x ret
ER4j
=O# t;2\(_A 1w|C+m/( mov bx,ax
fAHf}j mO|YX/> //W7$DYEG 而下面的子程序是不可重入的:
0ghW};[6 $CgR~D2G }k7t#O Add proc near
Bk)*Z/1<x )*tV ,'0Zd(s mov Temp,ax
}}4u>1,~ ,ag:w<km )~CnDk}^R mov ax,DS:word ptr [si]
AFN"#M =MCQNyf+ vD@=V#T cmp ax,0
"S ~(|G ICxj$b D<SLv,Y je DonotTheValue
!\RBOdw C E Qn4+ Q`* v|Lp add ax,Temp
$T%~t@Cv1 3|qT.QR`Z *W&}}iL DonotTheValue:
\ =(r6X gLGu#6YVu ugT;NB ret
I C?bqC+ zv>3Tc0R {P[>B}'rW Temp:
{~u#.
( 9S8>"w^R |2'u@<(Z/ dw 0
brXLx+H8 d=~-8]%\ DE659=Tq Add endp
F\
lnG