这个SideKick是个好东东。 pl? J<48
;jfXU_K
下面的程序不是我写的。 bu!<0AP"N+
D_`)T;<Sp
用汇编编写DOS下的内存驻留程序(1) SX<>6vH&
a~
+WL
xo@/k
(]uoN4
+vY`?k`
S+=@d\S}"
SX94,5 _Q
绪言 qv >(
hB1 iSm
Bk(XJAjY
0.1 内存驻留与中断 7UnO/K7oB.
\y+F!;IxL
&ppZRdq]
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 CX(yrP6;
oA^
]x>
t7&
GCZ
内存驻留程序的常用形式有: x[<#mt
5|H(N}S_
D}C*8s bC}
>诸如Borland 的SideKick弹出式实用程序 Ib<+m%Ac
c;
fyUi
+]2~
@=<@
>日历系统 kT3;%D^
K0bmU(Xxp
2H0q\zZ
>网络服务器 vVR
CM
&S`'o%B
9n2%7dLQ*
>通讯程序 XsCbJ[Z_?q
L
~'N6
Z)>a6s$ih<
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) - cC(d$y
Q14;G<l-
#SOj4W
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. _p^ "!
q>h+Ke
M;@03 x W
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: krT!AfeV
0hr)tYW,G
Bc`A]U
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. N1zrfn-VU
"h|0]y^2
n!,TBCNX
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. FKTP0e7=9
@G&xq"Fg7
m(Xr5hw:6
>以上各种的结合. YV+dUvz
s.Ic3ITd,
~]s"PV:|
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. )1'_g4
|0Ug~jKU
|UiykQ
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. ."g5+ xX
_z6u^#Si
[\y>&"uk
手式计算中断向量的首址,可通过以下的公式来求得: I>\?t4t
<{~UKi
B~?Q. <M
X号中断向量的首址=0000H:X*4 <Gt{(is
Aba%Gh
C F 0IP
当产生一个中断时,处理器都按顺序执行以下步骤: R-0Ohj
}tg n1xpx
"PP0PL^5F
>在堆栈上压入处理器的标志(相当于指令PUSHF). QRix_2+
B$eF@v"
k:yu2dQh
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). GOgT(.5
H s 3*OhK\
mAERZ<I
>关闭中断(CLI) V)?g4M3}
:l[Q
~ZIRCTQ"
>从中断向量加载的CS和IP,执行中断处理程序. Ny<G2!W
im%3*bv-
zb*4Nsda:
当执行完中断处理程序后,一般用IRET返回,它的作用是: `Y$5g~3.
YuuG:Kk
icbYfgQ
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). -s84/E4Y*
8-#2?=
+m},c-,=$w
>同时恢复中断前的处理器标志(相当于指令POPF). mhSsOmJ5
c7N9X 3A
Uv$u\D+@[
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. (9lx5
\Xp"I5
/ =<ul-K
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. 9E*K44L/V
J #5o
y.NArN|%
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. DccsVR`7
|1 6v4 R
_\6(4a`,
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. !S}Au Mw
z-E4-\a
pIjVJ9+j
u $^`hzfI
0.2 DOS的可重入性分析 Z-V%lRQ=b
h2*&>Mc
,3[<C)'[
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. u 9TlXn
=)>q.R9
`)P_X4e]`
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. ~#Mx&mZ
ml/O
S :|*wB
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: xL"o)]a=
DN_C7\CoA
*XR~fs?/*W
Add proc near S}I=i>QB
jv^L~<u
(NlEb'~+
cmp DS:word ptr [si],0 1Ac1CsK*
+`[Sv%v&L
a-hGpYJJG
je DonotAddTheValue f@g
I8:&Bt
f
0u9h2/ma
add ax,DS:word ptr [si] VAzJclB
y=`(`|YW}`
(!=aRC.-
DonotAddTheValue:
(pg9cM]NA
a
VMFjkW
Q*(C)/ QW
ret @=1``z#
&g {_.n,
,_-*/- 7;8
Add endp b
DvbM
1W7BN~p14
bME3" e{O
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. I(S6DkU
S?tLIi/
md
s\~l73
mov ds,0100h ;ds=0100h QQcj"s
SHh(ujz,
?5gpk1
mov si,0010h ;si=0010h DgP%Q
Hvk?(\x
pdu
mov ax,0001h ;ax,=0001h U$Z}<8
w\4m-Z{
N/=3B
s0y-
call Add (`xnA~BN
|g!#
\
e8v=n@0
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine pP&M]'
V0(ABi:d
a06q-3zw
push ds ;Interrupted {HDlv[O%
xUoY|$fI
P
ie!Su`
push si C_)>VP
D
(o\~2e:
h!]A(T\J
push ax }aIfIJ
g{(nt5|^l
'kK%sE
mov ds,0200h ;ds=0200h n-Y'LK40Os
z5/O8}Gz@
`7ZJB$7D|*
mov si,0200h ;si=0020h >c eU!=>
\]El%j4
gV;GC{pY
mov ax,0003h ;ax=0003h '_Op rx
&o.SmkJI
/L^dHI]Q
call Add {xH@8T$DX
m8'
1@1d|
6Fb~`J~s
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h
b5R*]
!}7m^
;{20Heuz
jne s9>!^MzBK
p-k qX
VV0$L=mo
add ax,0200h:word ptr [0020h] ;ax=0007h W@=ilW3RD
:Yqa[._AF
[l:.Q?? )|
ret ;Return 7L"/4w
Hq$|j,&?
eW%jDsC
pop ax ;ax=0001h sxtGl^,mU:
^Quy64M
Tkf !Y?
pop si ;si=0010h qiN'Tuw9
'~0&m]N
D$;/
l}s?
pop ds ;ds=0100h t"fD"Xpj
;;5i'h~?]J
}fZBP]<I(
iret ;Return to Add subroutine K(2s%
AJu.
@d|
9(,Q
jne
DAi[3`C
IgL8u
x
,W+:l9~s
add ax,0100h:word ptr [0100h] ;ax= 0001h k"$V O+}m
f6) H!SI
kF .
b)
;0100h:0010h= 0002h r MlNp?{_
ZxQP,Ys_Y
|zKcL3*
;---------------------------------------- 7O#>N}|
F^-4Pyq@
tHeLq*)
)
;ax = 0003h a6_`V;
;*p}~#2
%b9M\
ret VXS9E383
7j8_O@_
9m{rQ P/
mov bx,ax =UY@,*q:c
P9vROzXK
D.?gV_
而下面的子程序是不可重入的: `<q5RuU
.MlE1n'
%s>E@[s
Add proc near S y~ 1U
rB]/N,R
KMZ`Wn=
mov Temp,ax 4NIfQYC.
FReK
|*i-Q @
D
mov ax,DS:word ptr [si] jYv
!}
da@
.J9
@$]h[
cmp ax,0 tP-c>|cz
|Oe6OCPf
f`e.c_n(
je DonotTheValue ;nE}%lT
g:yK/1@Hk}
HFOp4
add ax,Temp z?xd\x
V5+a[`]
;f
Gi5=-
DonotTheValue: "/5b3^a
0'uj*Y{L
Hw?
J1#1IE
ret FceT'
.anL}OA_q
&0raa
Temp: ,")7uMZaF\
,U}8(D~:
_1ins;c52
dw 0 C'ZU .Y
"5Mo%cUp
Yi`.zm
Add endp }- Sr@bE