这个SideKick是个好东东。 )gZ yW
_f/6bpv
下面的程序不是我写的。 >y5~:L
D
,nF0p
用汇编编写DOS下的内存驻留程序(1) yJ?6B LJi
]`LMyt0
=m UtBD.;
d;K,2
d%iMjY`~[g
LKhUqW
2QdqVwm
绪言 Zf ;U=]R
V
V<Zl
U<zOR=_
0.1 内存驻留与中断 'Je;3"@
bO9X;}\6
rAgb<D@,H
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 U2;_{n*g%
5~v({R.
X4gs{kx}|
内存驻留程序的常用形式有: {$Qw]?Yv
Pwf":U)
hDCR>G
>诸如Borland 的SideKick弹出式实用程序 EsdA%`
@I9A"4Im
~OXPn9qPp
>日历系统 yN9/'c~
5-*/wKjLz
alyWp
>网络服务器 up1kg>i%"
}5EvBEv-)
+ps(9O/B>
>通讯程序 s~3"*
,3@
s_/CJ6s
QN":Qk(,q
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) q>t#5Z81
!Eu}ro.}
0`:0m/fsU
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. @u?m4v{
T)MKhK9\Ab
!IcPO
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: >o.4sN@
D/v?nW
.^eajb`:
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. G@s
rQum(
(V&$KDOA
b:2#3;)
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. W2'u]1bs
^tI
,eZ
idEhxvAo
>以上各种的结合. f-^JI*hj
?|kwYA$4o
13kl\<6
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. p[>!;qI
)m|)cLT&
f<<1.4)oSV
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. _->d41
X3@Uih}|
bZLY#g7L"
手式计算中断向量的首址,可通过以下的公式来求得: iU+O(vi
nH_M#
y2cYRHN[X}
X号中断向量的首址=0000H:X*4 F P3{Rp
Dr)B0]KG
*jM]:GpyoU
当产生一个中断时,处理器都按顺序执行以下步骤: Vmt$
]/
OQ&l/|{O0?
jBb:)
>在堆栈上压入处理器的标志(相当于指令PUSHF). JD9)Qelw^$
PKJ w%.-
z#m ~}
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). Cs))9'cD]
\I( g
70
Z):q 1:y
>关闭中断(CLI) KSz;D+L\
8MU+i%hd
&sJ -&7YZ
>从中断向量加载的CS和IP,执行中断处理程序. s+DOr$\
EV/DJ$C }
VX0}x+LJ
当执行完中断处理程序后,一般用IRET返回,它的作用是: NYw>Z>TD8c
DZ"'GQSg
Y'*oW+K
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). 6/6M.p
yw\Q>~$n[=
f}=>c|Do
>同时恢复中断前的处理器标志(相当于指令POPF). BlnR{Y
=bgWUu\F
id+ ~ V
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. GCZx-zD~>
W[/Txc0$
Ir#]p9:x
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. fN&@y$
}p5_JXBV
FF #T"y0Y
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. F
JCs$0
zcGmru|k
@q]4]U)
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. ? fW['%
XlLG/N
iSbPOC7
DaP,3>M
0.2 DOS的可重入性分析 8
kvF~d
;
,+~8R"
$+w:W85B
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. 2ci[L:U
%tB7 &%ut
Np7+g`nG
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. Q<0X80w>
]n}aePl}oU
pmRm&VgE.
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: V_zU?}lZ^
0RgE~x!hI
GHY+q{'#V_
Add proc near
jh(T?t$&
fJOwE
g|
K
@RGvP
cmp DS:word ptr [si],0 G>=Fdt7Oc
1%E
Ngb:8
nr&bpA/
je DonotAddTheValue rtNYX=P
M0yv=g
.exBU1Yk@
add ax,DS:word ptr [si]
e.\dqt~%y
Qp7h|<
ml@;ngmp.
DonotAddTheValue: DG?g~{Y~b
LI*=T
#lR-?Uh
ret bFjH*~
P
fqjBor}
'Fy"|M;2
Add endp 1oe,>\\
S4\a"WYg
t0,=U8]w
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. I3HO><of
PriLV4?
4O<sE@X
mov ds,0100h ;ds=0100h x
]">
IdqCk0lVD
'i',M+0>jC
mov si,0010h ;si=0010h JkhW LQ>o
C#-HWoSi
7r&lW<:>
mov ax,0001h ;ax,=0001h ^hXm=r4ozR
EHN(
K-
"}MP {/
call Add }yVx"e)
NOg/rDs'{
eAmI~oku
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine kDol 1v`
auga`*
nrHC;R.nE
push ds ;Interrupted (n`]
sbx
u@1 2:U$
DkX^b:D*f
push si `Fie'[F5,)
)r^vrCNy>
C~egF=w
push ax DQ(0
:r
P -NR]f
r0!')?#Z
mov ds,0200h ;ds=0200h `;Ho<26
rY6x):sC
#9gx
4U
mov si,0200h ;si=0020h R2v9gz;W
elAWQE us
FQJiLb._Z
mov ax,0003h ;ax=0003h }4N'as/ZO
)9^)t
To}eJ$8*5
call Add "4\k1H"_
Mgr?D
1
RJFPv
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h L&c
&
<+0T
U0t|i'Hx
K[kK8i+(
jne T%%
0W J
P0y DL:X[
~Oa$rqu%m
add ax,0200h:word ptr [0020h] ;ax=0007h 6@TU9AZS`
3_<l`6^Ns/
<o/!M6^:
ret ;Return ]!ox2m_U
$33E-^
SV@*[r
pop ax ;ax=0001h ?r KbL^2
Da615d
0N^+d,Xt.
pop si ;si=0010h d7Vp^^}(
(>vyWd]
<3!Al,!ej@
pop ds ;ds=0100h 1~t.2eU G
fGb}V'x}r
Tf~eH!~0
iret ;Return to Add subroutine
HdN5zl,q
,VS(4
.<zKBv
jne y_X
jY
FY^2 Y
=WjHf8v;
add ax,0100h:word ptr [0100h] ;ax= 0001h V:w%5'^3
cef[T(>
V1B!5N<
;0100h:0010h= 0002h b3EGtC}^
"]#Ij6ml
mFg$;F
;---------------------------------------- 23P&n(.
<4+P37^~
S=ZZ[E_~S
;ax = 0003h 5CZyA`3V^5
s]%Cz \
||JUP}eP
ret ;Ax-f04gG
E/g"}yR
o
!:Z?.!
mov bx,ax h~7#$i
)
w0x{_
(I
BT|K
而下面的子程序是不可重入的: "h#R>3I1)
@QV0l]H0+
j1KNgAo<4
Add proc near D#UuI
Z
tBbOxM m0
g!R7CRt%
mov Temp,ax g]lEG>y1R
+=jS!
8'u9R~})
mov ax,DS:word ptr [si] u
[._RA
yI 2UmhA
D3c
JIVM
cmp ax,0 gE
_+r
KEtV
rw,Ylr:3
je DonotTheValue /1MmOB
Xd=KBB[r?
^#d\HI
add ax,Temp RqgN<&g?
[02rs@c>
<mQX
S87
DonotTheValue: V
_:`K$
tsAV46S
l3sF/zkH
ret ?>Sv_0
7Y9#y{v1
T[Zs{S
Temp: ao2^3e
=}0Uw4ub(u
O;~e^ <*
dw 0 .26mB
Xr
1(-!TJ{
-T,?'J0 2
Add endp ~.aR=m\#