这个SideKick是个好东东。 OVO0Emv
Gy[;yLnX
下面的程序不是我写的。
P,RCbPC4
AqVTHyCu
用汇编编写DOS下的内存驻留程序(1) z602(mxGg
Egt;Bj#%
iV#JJ-OBq
cL*D_)?8
|u)?h]>
{+f@7^/i.
6w K=
绪言 LGT\1u
HzB&+c?Z
,=lMtW
0.1 内存驻留与中断 /:>f$k4~h
/_rAy
L>{E8qv>w
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 2F-!SI
JJ56d)37.
64}Oa+*s
内存驻留程序的常用形式有: BQf}S
+
&0TOJ:RP
9\*xK%T+
>诸如Borland 的SideKick弹出式实用程序 YZ\$b=-
!lE
(!d3M
=mCUuY#
>日历系统 NFGC.<
k%QhF]
JnCY O^Qj
>网络服务器 !U#kUj:4I
zW%-Z6%D
f+0dwlIlC$
>通讯程序 } oJ+2OepN
D8_m_M|P
9>psQ0IRvr
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) ~fsAPIQ
io
cr
GFvZdP`s4
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. xc R
xkl'Y *
>H@
dgb
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: zsI0Q47\
;9c3IK@
D0PP
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. 9A\J*OU
n6WSTh
H;s0|KRgJ
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. ,*0>CBJvv
G Q&9by=}
-;T>4B=
>以上各种的结合. mKZ?H$E%%
%Zx/XMs}e
n4)G g~PE
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. :<%K6?'@^
O:q}<ljp
%Ua*}C
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. \~xsBPX+x
AEK * w4
xXZ$#z\Z,
手式计算中断向量的首址,可通过以下的公式来求得: g=pz&cz;>\
uf`o\wqU
G5zZf~r
X号中断向量的首址=0000H:X*4 8_f0P8R!y
po"M$4`9
-w 2!k
当产生一个中断时,处理器都按顺序执行以下步骤: @Th.=
133lIX+(k
-!"
>SY\
>在堆栈上压入处理器的标志(相当于指令PUSHF). dk({J
yVQqz
}*$-rieg
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). <
PW*vo9v
Y,WcHE
,e>C)wq;
>关闭中断(CLI) m&,d8Gss^
5gI@~h S
IJq$GR
>从中断向量加载的CS和IP,执行中断处理程序. F$ Us! NN
e }/c`7M
c@
En4[a'
当执行完中断处理程序后,一般用IRET返回,它的作用是: ]V]~I.
i[d-n/)
M O* m@
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). -O~WHi5}
6luCi$bL
2DTH|Yv
>同时恢复中断前的处理器标志(相当于指令POPF). 0"u*K n
m*P~X*St
bEbO){Fe
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. J~ v<Z/gm
a%ec: %
G#duZNBdc
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. B/E1nBobC
S=[K/Kf-
N&S:=x:$S
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. ekI1j%fO
9|jIrS%/~
;eG
%#=>
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. UOF5&>MLb
{_3ZKD(\
8[f]9P/i
nP'ab_>b
0.2 DOS的可重入性分析 ?Pl>sCFm~
@)VJ,Ql$Y
`;*=2M<c
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. o'myo
.k{
2K,
1wqf'
h'UWf"d
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. X
a<siA{
]ZO^@sH
|Y/iq9l
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: B_`A[0H
lhQ*;dMj%"
{>QrI4*A
Add proc near -K
}@Gp
lqqY5l6j
HJBUN1n
cmp DS:word ptr [si],0 BEPDyy
$+JaEF`8
A &w)@DOe
je DonotAddTheValue 3KB)\nF#%
&[S)zR=?
w
\0=L=J
add ax,DS:word ptr [si] y+Q!4A
Zi7(lG
HtY\!_Ea
DonotAddTheValue: Fxv~;o#
"5XD+qi
:BMU c-[
ret 5[I> l
4x8mJ4[H^
Jd1eOeS
Add endp .d8) *
sXoBw.^Ir_
'y
cs{}'
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. sdS<-!
%u4
_}jj>+zA`
z(
1h ^.
mov ds,0100h ;ds=0100h =h&DW5QC
QHMXQyr(
@!%<JZEz3
mov si,0010h ;si=0010h J5J3%6I
(O&~*
7D*
Gjy'30IF
mov ax,0001h ;ax,=0001h * +A!12s@
*XtZ;os]
vU{ZB^+&6o
call Add 5Odi\SJ&
.s7/bF
a^Zn
}R r
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine 1Lj\"+.
3w{i5gGn
#J2856bzS
push ds ;Interrupted !3yR?Xem}
q;kMeE*
?A62VV51CN
push si 4D\_[(P
*WMcE$w/D
*#UDMoz<
push ax 4I
y\
|C>Yd*E,C
e5`{*g$i).
mov ds,0200h ;ds=0200h 6_zL#7E'
VJ_E]}H
1grrb&K
mov si,0200h ;si=0020h A*\4C3a'%
f_raICO{R
Y
3KCIL9
mov ax,0003h ;ax=0003h +#&2*nY
1
f[!=p
d9Rj-e1x
call Add wy) Frg
HLk}E*.mC
/ d6mlQS
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h I
&{dan2
C:4h
}b\d CGVr
jne 5^*
d4[&+
?r'
b
Z~
db#y]>^l
add ax,0200h:word ptr [0020h] ;ax=0007h ",Q \A I
lZn <v'y
4,$x~m`N
ret ;Return Grjm9tbX}
{R1jysGtD
Q~-g tEv+&
pop ax ;ax=0001h #+Vvf
S'3l<sY
cE]tvL:g
pop si ;si=0010h ;Kkn7&'F
T w"^I*B
{_(;&\5
pop ds ;ds=0100h BIcE3}dS8
? `FI!3j
,dh*GJ{5
iret ;Return to Add subroutine /tt
NO* 1km[#
_V8pDcY
jne Lk3@Eu)
Y;#P"-y
H
9^
mrsj
add ax,0100h:word ptr [0100h] ;ax= 0001h yRieGf1'SD
3)Paf`mr
,T&B.'cq
;0100h:0010h= 0002h ,C=Fgxw(
^=R>rUCmv
,qvz:a
;---------------------------------------- 4s"8e]q
=
b;x^>(It
H%faRUonz
;ax = 0003h
d>vGx
sBRw#xyS
~f% gW
ret Q`19YX
4qyL' \d[
cHJ
&a`;
mov bx,ax pOH_ CXw
ej!
C^
M6 0(yTm
而下面的子程序是不可重入的: <'GI<Hc
Pi+,y
7sLs+|<"
Add proc near +8BH%f}X
aNXu"US+Sp
o"UqI
mov Temp,ax =gfLl1wY[
_Dk;U*2
S4?ssI
mov ax,DS:word ptr [si] 2]>s@?[
b,318R8+G
'{OZ[$E
cmp ax,0 5%4:)s{4|
m! p'nP
kTC6fNj[
je DonotTheValue Sl 6}5
CiPD+I
W"wP%
add ax,Temp '>`bp25>
Xv:<sX
v5<Ext
rV
DonotTheValue: KtV_DjH:
- }
Z
^$x^JM ]/
ret r ."Dc
IOIGLtB
i 3?zYaT
Temp: +Do7rl
H%])>
1Z`<HW"
dw 0 <[a9"G7
YtIJJH
\".3x
PkE
Add endp z),l&7