这个SideKick是个好东东。
7oA$aJQ
?;>s<
下面的程序不是我写的。 YNc%[S[u^1
>4}+\ Q`S
用汇编编写DOS下的内存驻留程序(1) r
Efk5R
ur={+0
y
_X;^'mqf~
X<\^*{
y;Q_8|,F
#Bj{
4OeV
3!Zd]1$
绪言 U`K5 DZ~
Smo^/K`f9
I!9u](\0
0.1 内存驻留与中断 1c~c_Cc4
?VEJk,/k
/@R|*7K;9
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 SEXe
K2v
qd~)Ya1
<8 Nh dCO6
内存驻留程序的常用形式有: [Av87!kJ!X
;j=/2vU~@
kNUbH!PO
>诸如Borland 的SideKick弹出式实用程序 'e02rqip{
5[`!\vCiZ
mA(K`"Bfh
>日历系统 QW6F24
5fv eQI~!
#!rng]p
>网络服务器 l-_voOP
w;0NtV|
VF!?B>
>通讯程序 LD: w
wH
\hQ[5>
jC
,foqL
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) E}c(4RY
dMw7Lp&
<i^Bq=E<rJ
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. +`kfcA#pi
6g8{;6x
5!}xl9D
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: K8Gc5#O
F
5X\3y4
|4YDvDEJi
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. ye KzI~
gC;y>YGP
!cE>L~cza
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. !jMa
%;/
vrm[sP
@YdS_W
>以上各种的结合. )+wBS3BC
G^p>fy~
Z66akr
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. wblEx/FqE^
v~q2D"
gR.zL>=_5e
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. D^=_408\
;nji<
epCU(d*b
手式计算中断向量的首址,可通过以下的公式来求得: Nz#T)MGO`
PP/M-Jql)
Dk&cIZ43
X号中断向量的首址=0000H:X*4 g
Z
\ :8~na+(
E{^*^+c"h
当产生一个中断时,处理器都按顺序执行以下步骤: N/DcaHFYo
~l}rYi>g%
}D xXt
>在堆栈上压入处理器的标志(相当于指令PUSHF). 9@./=5N~3
e{:P!r
aM
:g2?)Er-
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). Kpz>si?CL
(
Z\OqG
OZ&J'Y
>关闭中断(CLI) Bt[`p\p@
@JT9utct
%Z 9<La
>从中断向量加载的CS和IP,执行中断处理程序. 3qiE#+dC
8/U=~*`_
;{ XKZ}
当执行完中断处理程序后,一般用IRET返回,它的作用是: m;WUp{'
yX$I<L<Suz
iN0pYqY*
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). BZQ98"Fz*
apF!@O^}y
<?&GB
Ce
>同时恢复中断前的处理器标志(相当于指令POPF). C 6Bh[:V&
9'o!9_j
;i^p6b j
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. b9)%,3-
"u Xl
M<r'j $g
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. jiYYDGs77
7_.z3Km:
kwMuL>5
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. ~1`.iA
enj
Ti5X
}Ga@bY6
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. <_uLf9ja
Q mOG2
-dsB@nPiUw
lu`\6
0.2 DOS的可重入性分析 ct3QtX0B
Pr{? A]dQ
Z6!MX_ep
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. '$ ~.x|
- 6;0 x
}C/u>89%q
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. 9b@L^]Kg
L^KGY<hp4
/YR*KxIx
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: + G"=1sxJ
[^A.$,
Kw3fpNd
Add proc near {0q;:7Bt
Z_}vjk~s
El Z'/l*\
cmp DS:word ptr [si],0 p H5IBIf'
F}DdE
rd!f
DOaEz?2)
je DonotAddTheValue Rs_@L}U..
>"f,'S5*
X |.'_6l.
add ax,DS:word ptr [si] %'kaNpBz
1HskY| X
4
`Z @^W
DonotAddTheValue: (;$J5
?1?^>M
}.3F|H
ret 3Ku!;uo!u
-i V&-oP
'(5 &Sj/C
Add endp G`ZpFg0Y
5UVQ48aT
@%IZKYfc~
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. n }7DL8
oylY1~~}0K
SGZOfTcY
mov ds,0100h ;ds=0100h +&jW
M-T"-
[Oxmg?W
_K)B
mov si,0010h ;si=0010h H;k;%Zg;
<P3r+ 1|R
7fLLV2
mov ax,0001h ;ax,=0001h <t,uj.9_
Dp6]!;kx
H4Ca+;
call Add 3q R@$pm
2*vOo^f
5znLpBX<N
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine XASoS5
xH;qJRHa
{W3%n* q
push ds ;Interrupted M
E[Wg\
i@6MO'y
o
\@1\#a
push si gAhC
NOp
~cz]Rhq
lJ3/^Htn
push ax ^
b~&}uU
TgSU}Mf)a
}pbyC
mov ds,0200h ;ds=0200h b3wE8Co
W'E!5T^
5`{ +y]
mov si,0200h ;si=0020h .6!IO^`[
F:%= u
=
C?#if;c
mov ax,0003h ;ax=0003h <GF)5QB
K7FuMB
_b<Fz`V
call Add F8 ;M++
"FT5]h
Nv,[E+a2
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h (sW:^0 p
O_nk8
4;M
jne b,Ed}Ir
mn{8"@Z
3P6pQm'.f
add ax,0200h:word ptr [0020h] ;ax=0007h nZfTK>)A0
P!,\V\TY]
U#ueG
ret ;Return xrA(#\}f$
p>Ju)o
tE]g*]o
pop ax ;ax=0001h j1N1c~2
<]b}R;9v
Z@nM\/vLA
pop si ;si=0010h };+ '
?g}n$%*5y!
'X_iiR8n@p
pop ds ;ds=0100h ^TyusfOz
::uD%a zd
DdJxb{y7
iret ;Return to Add subroutine %/,PY>:|
RV.zxPw>>
?;0=>3p*0
jne `4.Wdi-Si
4\pi<#X
]cc4+}L~
add ax,0100h:word ptr [0100h] ;ax= 0001h ;Z-Cn.
5>t&)g
Q
nDy mVF
;0100h:0010h= 0002h lN,b@;
I}puN!
!aeL*
`;
;---------------------------------------- N:)`+}
d0>V^cB '?
I.fV_
H^
;ax = 0003h ~q?IG5s*Z
n4 KiC!*i0
R
ecA?-0
ret Bg-C:Ok2'
~2
T_)l?
-DlKFN
mov bx,ax LXVm0IOFF
k)'hNk"x
%;!@\5$
而下面的子程序是不可重入的: =jkC]0qx
[zm&}$nnN
aP!a?xq
Add proc near MnO,Cd6{%d
?|%^'(
U}
":"QsS#*"#
mov Temp,ax h.%VWsAO7
H:`W\CP7_
#~Lh#@h
mov ax,DS:word ptr [si] HyiuU`
Lbq
"( b
Xf:CGR8_
cmp ax,0 &"._%
S58V
fNFdZ[qOd
Gs7mO
je DonotTheValue Sr)/
Mf
?Gp~i]
^OI
add ax,Temp .lb2`!'r&
jm =E_86_
vYL{5,t {1
DonotTheValue: ~4U[p 50
c#OZ=`
4(R O1VWsb
ret Fh?;,Z
)*G3q/l1u6
//JF$o=)
D
Temp: s^^X.z ,
DvG. G+mo#
6^wg'u]c
dw 0 +#6WORH0S
?f1%)]>
ci+Pg9sS
Add endp YZ7rs]A