这个SideKick是个好东东。 #1[u(<AS
rs.)CMk53
下面的程序不是我写的。 2?x4vI
np;
:pUtSs7p}
用汇编编写DOS下的内存驻留程序(1) cu6Opq9
Lr<cMK<
S[N5 ikg
/E>e"tvss
`2snz1>!j
6nQq
u4j5w
绪言 *](iS
n| ;Im&,
he4(hX^
0.1 内存驻留与中断 ~m |BC*)
*8Z32c+C
BzzTGWq\
内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行。 626r^c=
+d>IHpt
iB{V^ksU
内存驻留程序的常用形式有: :
-'qC8C
AR=]=8
7 3m1
>诸如Borland 的SideKick弹出式实用程序 $C\BcKlmv
ceV}WN19l
ZW}_DT0
>日历系统 ?8$Q-1=
}'.m*#Y
MPV5P^@X
>网络服务器 oQ# 8nu{k
^s=8!=A(
nK,w]{<wG!
>通讯程序 ]tD]Wx%
=}*0-\QG
ys~x$
>本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴) Uv.)?YeGh
OYd !v`<
ise-O
1'
>一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所有的病毒程序都是TSR程序. OCU
r{Nh
+0~YP*I`/
'%D7C=;^
就象多任务系统调度一个进程有一个调度程序一样,在PC中从前台程序进入到一个TSR,也要有一个调度者,只是PC操作系统的调度不称为调度程序,而只称为触发机制.触发机制调度TSR执行在PC机上党称为激活一个TSR.触发机制主要有以下几种: :>*7=q=
pFXEu=$3
/ +\9S
>硬件中断:党用的是键盘中断INT 9H,时钟中断INT 8H,通讯中断INT 14H,磁盘中断INT 13H等等. J *yg&
8RX&k
s CRdtP
>软件中断:党用的是键盘中断INT 16H,时钟中断INT 1CH,DOS中断INT 21H,等等. ! z**y}<T
2?5>o!C
Z7#+pPt!
>以上各种的结合. E3i4=!Y
"#] $r
w &(ag$p'
从以上的触发机制可以看出,TSR和PC机的中断系统有着密切的关系.每种激活方式实际上都是与中断有关的.常用特殊的击键序列的识别码是通过截获INT 9H和INT 16H来实现.实际上不管TSR程序的哪一个环节,都与中断有着密切的关系.因此在具体进行TSR和程序设计之前,先介绍PC中断系统.在此只作简单说明. g ?
k=^C
+H.`MZ=
<m m[S
在PC机内存的最低端(0000H开始)的1K字节中,存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor),每个中断向量都指向一个子程序,该程序称为中断处理程序(Interrup handler).一个中断向量由四个字节组成,有一个字是中断处理程序的偏移量值,后一个字是中断处理程序的段值.256中断向量一起称为中断向量表. ;I*o@x_
>bxS3FCX
{FGj]*
手式计算中断向量的首址,可通过以下的公式来求得: .h[:xYm
NgwbQ7)
?0SEMmp`H
X号中断向量的首址=0000H:X*4 VnzZTGs
xmX 4qtAL
9FvFhY
当产生一个中断时,处理器都按顺序执行以下步骤: /mMV{[
G"6 !{4g
1,~D4lD|
>在堆栈上压入处理器的标志(相当于指令PUSHF). zTp"AuNHN
OPi0~s
K
P"+e:a%
>在堆栈上压入当前CS和IP值(相当于指令PUSH CS和PUSH IP). `gJ(0#ac
U17d>]ka
Vj-h;rB0z
>关闭中断(CLI) ?`#Khff?
7"##]m.
>V937
>从中断向量加载的CS和IP,执行中断处理程序. nEfK53i_
%;/P&d/
GmG5[?)
当执行完中断处理程序后,一般用IRET返回,它的作用是: %RVZD#
zr
g\U-VZ6;p
9z0p5)]n>
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS). )7d&NE_
G6/m#
S 5U;#H
>同时恢复中断前的处理器标志(相当于指令POPF). ZoeD:xnh[
pJ=#zsE0
C}X\|J
中断有多种分类,由触发的原因和实现的性质来分,可分为硬件中断和软件中断,从操作系统分层实现来说,可以分成BIOS中断,BOS中断和用户中断. GeqP
Rah
),)lzN%!
qLCR] _*
一方面,BIOS和DOS通过中断系统向用户提供一个操作系统功能界面.也就是说用户(一般来说是前台程序)的功能主要是通过调用DOS和BIOS的中断服务来实现的,具体来说就是通过INT指令来实现的.另一方面,BIOS和DOS由中断系统所构成,BIOS对硬件成为高层的功能,并通过中断的形式向用户提供. 5bIw?%dk(
2T1q?L?]
u y+pP!<
如果在当前程序执行的同时,能将一块代码放在内存,把中断向量指向代码中的子程序,那么在当前程序执行中产生中断时,就有可能执行不属于当前程序和操作系统的代码,产生的中断可能是当前程序产生的软件中断,也可能是由硬件产生的硬件中断.这就是单任务的PC操作系统可能执行多于一个进程的简单说明. -} +[
=vPj%oLp'a
mR~&)QBP.
在PC中断系统中有几个中断具有周期性,即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于时间计时,或者周期性产生用于等待.它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机制.此外众多的软件中断也是触发的媒介. ~@!bsLSMU
s.#`&Sd>
&L:!VL{I
j+!v}*I![
0.2 DOS的可重入性分析 l.]xB,k
G)YcJv7
~[
F`"
一个多任务操作系统之所以能使多个进行并存,是因为操作系统的大部分代码是可以了重的,对于临界资源有相应的PV操作,使得当调度一个新的进程时,能完整地保存前一个里程的现场,当再一次调度被挂起的进程时能象没有被中断一样继续执行. D@KlOU{<
i?/qY&~
\G BuWY3B
对于PC机来说,代码的重入性比较弱,对临界资源没有PC操作.当我们用中断程序启动用户的TSR时,如果只保存标志和寄存器,以及当前进程一些信息,那么只保存了当前程序的一部分现场,DOS的临界资源不会自动保存.在进行TSR设计时,一定要了解PC操作系统的重入性和临界资源. ZC?Xqp
b'g )
>sF)BoLc
重入性总是体现在代码上,所谓可重入代码的指这样的代码,即该代码被执行时还没有从中退出,由于某种原因又一次或者多次进入相同的代码,该代码每次的执行结果都是正确的,就说该代码是可重入的.相反,如果结果不正确,那么就就该代码是不可重入的.下面是一个可重入的子程序的例子: edD)TpmE,
fOHxtHM
0%B/,/PxD
Add proc near bLL2
9^x> 3Bo
us.~G
cmp DS:word ptr [si],0 QWU[@2@%r
QnDg6m)+
E{\2='3\
je DonotAddTheValue D=$)n_F
5xBbrU;
YQ}o?Q$z
add ax,DS:word ptr [si] 6LZCgdS{
Q/?$x*\>
}qUX=s
GG
DonotAddTheValue: *
v`eUQ:
{_}I!`opr$
3'Rx=G'
ret /}$+uBgJm
hb-%_c"kq
vX>)je5#
Add endp uNyVf7u
So6x"1B
_GPe<H
上面的例子不管在其中任何一处再一次执行该子程序,执行结果不变.为了说明,只举多种可能性中的一种. @ZJS&23E
3R/bz0 V>
FwK]$4*
mov ds,0100h ;ds=0100h Smh,zCc>s
*Ly6`HZ9
N#]ypl
mov si,0010h ;si=0010h [7-?7mp!B
F{w
zB
3^ClAE"8
mov ax,0001h ;ax,=0001h sT.ss$HY9,
l}h!B_P'
iCoX&"lb
call Add
2eogY#
QPx^_jA
K:M8h{Ua
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine k+/6$pI
rOYx
b }1
h(4v8ae
push ds ;Interrupted yauvXosX
GY*p?k<i
]|@^1we
push si @iiT<
54,er$$V
+_!QSU,@
push ax xk5]^yDp
@W<m4fi
bD^owa
mov ds,0200h ;ds=0200h wL1MENzp*z
}vuARZ>
RCrCs
mov si,0200h ;si=0020h Y2Tt
Y;
<b.D&
{:s
f7
mov ax,0003h ;ax=0003h TC('H[
]
x^ni1=kU
Sdo-nt
call Add `^vE9nW7
s"|Pdc4
hPh-+Hb
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h z}<^jgJ
im8
CmQ
r%_djUd
jne `L
zPotz
:s,Z<^5a)g
)BE1Q*=
n
add ax,0200h:word ptr [0020h] ;ax=0007h aXVFc5C\
OI*H,Z"
bcyzhK=
ret ;Return kM6
Qp
.}t
e>]A*
]5O~+Nf
pop ax ;ax=0001h e.> P8C<&
GdwVtqbX
0b>h$OU/
pop si ;si=0010h 9?$i?
l}
/F*
DXo|.!P=3
pop ds ;ds=0100h .`lCWeHN
K9[UB
J,hCvm
iret ;Return to Add subroutine 1oS/`)
' QG?nu
'91/md5
jne M}a6Vu9
txpgO1
_$'ashF
add ax,0100h:word ptr [0100h] ;ax= 0001h #spCtZE
Z;i:](
}C:r9?T
;0100h:0010h= 0002h ^~dWU>
sK{e*[I>W
O^.#d
;---------------------------------------- [
3Gf2_
5R-6ji
7v kL1IA
;ax = 0003h RN1_S
0[`^\Mv4y
Hz~zu{;{J
ret _#niyW+?~
:h$$J
lP
r$1Qf}J3=
mov bx,ax eRYK3W
!VJoM,b8
)4OxY[2J
而下面的子程序是不可重入的: _-D{-Bu#
1x)J[fyId
y
fSmDPh
Add proc near +z( Lr=G
D-c4EV
NUZl`fu1Z4
mov Temp,ax ]lbuy7xj63
p ?!/+
b-DvW4B
mov ax,DS:word ptr [si] =(Mch~
8mMQ[#0:}
3Ul*QN{6
cmp ax,0 hrn+UL:d
=&]L00u.
7r!x1
je DonotTheValue @- xjfC\d
Wri<h:1
s*[bFJwN
add ax,Temp )UR7i8]!0
pkzaNY/q
%;_MGa
e
DonotTheValue: E.TAbD&5(
WY/}1X9.%
:]KAkhFkbb
ret O?2DQY?jT
>j/w@Fj
t!XwW$@
Temp: NJ<F>3
WLT"ji0w2
n[z+<VGwC
dw 0 (e~N
q
*p U x8yB
WMdg1J+~
Add endp wz%-%39q%