﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Testing-随笔分类-System</title><link>http://www.cppblog.com/testing/category/2758.html</link><description>Map out your future hut do it in pencil </description><language>zh-cn</language><lastBuildDate>Mon, 26 May 2008 05:51:17 GMT</lastBuildDate><pubDate>Mon, 26 May 2008 05:51:17 GMT</pubDate><ttl>60</ttl><item><title>映射ＲＯＭ－ＢＩＯＳ地址</title><link>http://www.cppblog.com/testing/archive/2006/10/04/13352.html</link><dc:creator>testing</dc:creator><author>testing</author><pubDate>Wed, 04 Oct 2006 12:56:00 GMT</pubDate><guid>http://www.cppblog.com/testing/archive/2006/10/04/13352.html</guid><wfw:comment>http://www.cppblog.com/testing/comments/13352.html</wfw:comment><comments>http://www.cppblog.com/testing/archive/2006/10/04/13352.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/testing/comments/commentRss/13352.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/testing/services/trackbacks/13352.html</trackback:ping><description><![CDATA[
		<font size="2">摘要：本文介绍了一种针对ｉ３８６以上ＩＢＭ个人计算机动态改写ＲＯＭ－ＢＩＯＳ <br />的方法，对于编写密钥仿真程序或调试ＢＩＯＳ程序有较高的实用价值。 <br />关键词：ＲＯＭ－ＢＩＯＳ，线性地址，逻辑地址，页目录，页表 </font>
		<p>
				<font size="2">一、问题的提出 <br />ＲＯＭ－ＢＩＯＳ是ＩＢＭ系列兼容机的基本输入输出系统程序，其中含有磁盘、 <br />键盘、通讯等基础功能的常规例程。在有些情况下，如调试修改过的ＢＩＯＳ程序，或 <br />需要通过ＢＩＯＳ截获某个中断调用，就希望能够方便地改写ＢＩＯＳ的内容。然而， <br />ＢＩＯＳ是写在ＲＯＭ当中的，不易修改。那么，是否有其它变通的办法呢？ </font>
		</p>
		<p>
				<font size="2">二、８０３８６的分页内存管理 <br />为了达到上述目的，可以考虑８０３８６及更高性能的处理器所采用的保护方式。 <br />其中的分页内存管理机制提供了线性地址到逻辑地址的对应关系。大家可能都有在 <br />ＷＩＮＤＯＷＳ下同时运行多个ＤＯＳ进程的经验。显然，ＷＩＮＤＯＷＳ通过分页内 <br />存管理为多个ＤＯＳ进程提供了０－１Ｍ的逻辑地址空间，同时启动了多个Ｖ８６模式 <br />任务。所幸的是，当我们启动计算机时，只要加载了ＥＭＭ３８６．ＥＸＥ这一内存管 <br />理驱动程序，我们就已经处在了分页内存管理的环境之中。 <br />为了进行更深入的讨论，有必要先介绍一下８０３８６分页内存管理的具体过程。 <br />８０３８６的分页部件包含两级分页管理，如图所示。页目录及页表每项均由４个字节 <br />构成，而每一页目录及页表都为４Ｋ字节，因此，每级页表含１０２４项。每页内存块 <br />大小也是４Ｋ，一个页目录可以映射１０２４个页表，从而映射全部４Ｇ字节的线性地 <br />址。 <br />当进入ＥＭＭ３８６．ＥＸＥ后，当前页目录的第一项所指的页表就是０－１Ｍ逻 <br />辑地址空间对应的页表。该表的第一项是逻辑地址０：０－０：ＦＦＦ，第二项是逻辑 <br />地址１００：０－１００：ＦＦＦ．．．最后一项是ＦＦ００：０－ＦＦ００：ＦＦＦ <br />分别对应的线性地址页号。 </font>
		</p>
		<p>
				<font size="2">三、编程实现 <br />要得到当前页目录，可以将控制寄存器ＣＲ３去掉低１２位的内容，即为当前页目 <br />录所在的页。不过，这一线性地址在０－１Ｍ的逻辑地址中是不可见的。如果不想使用 <br />保护模式下编程，可以考虑ＢＩＯＳ提供的线性地址的数据拷贝服务。中断号１５Ｈ， <br />功能号８７Ｈ。 <br />调用参数： <br />入口 ＡＨ＝８７Ｈ <br />ＣＸ＝拷贝字数（ＷＯＲＤ） <br />ＥＳ：ＳＩ＝拷贝过程中使用的全局描述表（ＧＤＴ） <br />ＤＢ １６ ＤＵＰ（０） <br />ＤＷ 源块字节数 <br />ＤＢ ３ ＤＵＰ（？）；源块线性地址 <br />ＤＢ ９３Ｈ <br />ＤＷ ０ <br />ＤＷ 目的块字节数 <br />ＤＢ ３ ＤＵＰ（？）；目的块线性地址 <br />ＤＢ ９３Ｈ <br />ＤＢ １８ ＤＵＰ（０） <br />出口 Ｃ＝１出错 <br />ＡＨ＝０成功，＝１奇偶校验错，＝２被中断，＝３ Ａ２０失效 <br />下面提供一个实例，它修改页表，将最后一项（ＦＦ００：０－ＦＦ００：ＦＦＦ） <br />重新映射到程序的ＲＡＭ地址空间，并将ＦＦ００：ＦＦＢ处的内容改写为‘９９’的 <br />ＡＳＣＩＩ码（在笔者所用的计算机上，该地址处为‘９６’的ＡＳＣＩＩ码）然后驻 <br />留内存。此处为ＢＩＯＳ时间的年号，此时再用ＭＳＤ查看，会显示ＢＩＯＳ生产时间 <br />为９９年。若想继续修改ＢＩＯＳ内容，只需修改其映射的ＲＡＭ地址空间。 </font>
		</p>
		<p>
				<font size="2">四、结语 <br />利用本文提供的方法，可以生成功能很强的密钥仿真程序，在ＲＯＭ－ＢＩＯＳ区 <br />域截取来自加密软件的读磁盘调用，从而可以获得密钥或仿真密钥。对磁盘加密软件提 <br />出了严重的挑战。另外，利用这一方法来动态改写及调试ＢＩＯＳ程序也不失为一种简 <br />单有效的方法。 </font>
		</p>
		<p>
				<font size="2">├─────┤ <br />├─────┤ │ │ <br />│ ├──→├─────┤ <br />├─────┤ │ 用户页面 │ <br />├─────┤ │ 页表 │ └─────┘ <br />┌───┐ │ 页目录 ├──→└─────┘ <br />│ＣＲ３├──→└─────┘ <br />└───┘ </font>
		</p>
		<p>
				<font size="2">附图：８０３８６两级分页图 </font>
		</p>
		<p>
				<font size="2">2) 页式管理的地址映射</font>
		</p>
		<p>
				<font size="2">首先要说明的是页式管理完全可以在没有段式管理的基础上实现，但是为了实现保护模式和以前的内存管理模式相兼容，才不得不在段式管理的基础上实现页式管理。<br />这样由段式管理而映射出的线性地址（没有页式管理前即为“物理地址”）就和以前由段式管理映射出的物理地址含义不同了。线性地址的具体含义如下：<br />typeded struct <br />{<br />unsigned int dir:10; // 表示页面表目录的下标，该目录指向一个页面表<br />unsigned int page: 10; // 表示页面表的下表，该表项指向一个物理页面<br />unsigned int offset:12; // 在4K字节物理页面内的偏移量<br />}线性地址</font>
		</p>
		<p>
				<font size="2">下面详细说明页式管理的内存映射过程：<br />a) 在CR3寄存器中取得页面目录的基地址。<br />b) 以线性地址中的dir项为下标，在目录中取得相应页面表的基地址<br />c) 以线性地址中的page项为下标，在所得的页面表中取得相应的页面描述项。<br />d) 将页面描述项中给出的页面基地址与线性地址中的offset项相加得到物理地址</font>
		</p>
<img src ="http://www.cppblog.com/testing/aggbug/13352.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/testing/" target="_blank">testing</a> 2006-10-04 20:56 <a href="http://www.cppblog.com/testing/archive/2006/10/04/13352.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>中断发生时候</title><link>http://www.cppblog.com/testing/archive/2006/10/04/13351.html</link><dc:creator>testing</dc:creator><author>testing</author><pubDate>Wed, 04 Oct 2006 12:54:00 GMT</pubDate><guid>http://www.cppblog.com/testing/archive/2006/10/04/13351.html</guid><wfw:comment>http://www.cppblog.com/testing/comments/13351.html</wfw:comment><comments>http://www.cppblog.com/testing/archive/2006/10/04/13351.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/testing/comments/commentRss/13351.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/testing/services/trackbacks/13351.html</trackback:ping><description><![CDATA[
		<p>
				<font size="2">中断发生时候,CPU自动调用相应的中断处理程序,这些中断处理程序的入口指针(被称作中断向量)一般被放在一个指定的位置,比如BIOS中断向量放在地址0-1K的空间内,每4个字节存放一个中断向量.而在保护模式下,BIOS中断不可用,中断向量被放在IDT中,当一个中断发生时,CPU将中断号作为索引到相应的中断处理程序表中(BIOS中断向量表(实模式)或IDT(保护模式))找到相应的中断处理程序的指针,并执行它. </font>
		</p>
		<p>
				<font size="2">另外,中断处理程序用C/C++还是ASM,还是机器语言写的并不重要,因为编译之后都是二进制机器指令或数据.但如果你的中断处理程序有空间和效率的限止,则一般使用汇编语言写,比如BIOS中断处理程序都是用汇编写的,被放在0xB0000-0xFFF00之间,而保护模式下,被OS开发者写的中断处理程序一般都是用C写的,比如linux.这些都不重要. <br />还有就是,BIOS中断处理程序被固化在ROM中,但BIOS中断向量表却是在PC启动时被POST(Power-On Self Test,是一段被固化在ROM中的程序)初始化在RAM中的,因此,你可以修改这些向量,让它们指向你自己写的程序.这样当中断发生时, CPU就会执行你所写的中断处理程序. </font>
		</p>
		<p>
				<font size="2">对于那些针对硬件操作的中断处理程序,我们看起来只要调用这些中断,就可以达到对硬件操作的效果(比如磁盘操作,显示器操作等等),但事实上,这只不过是中断处理程序直接调用I/O操作(in或out指令)来帮你完成了这一切罢了.</font>
		</p>
<img src ="http://www.cppblog.com/testing/aggbug/13351.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/testing/" target="_blank">testing</a> 2006-10-04 20:54 <a href="http://www.cppblog.com/testing/archive/2006/10/04/13351.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MBR加载过程</title><link>http://www.cppblog.com/testing/archive/2006/10/04/13350.html</link><dc:creator>testing</dc:creator><author>testing</author><pubDate>Wed, 04 Oct 2006 12:53:00 GMT</pubDate><guid>http://www.cppblog.com/testing/archive/2006/10/04/13350.html</guid><wfw:comment>http://www.cppblog.com/testing/comments/13350.html</wfw:comment><comments>http://www.cppblog.com/testing/archive/2006/10/04/13350.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/testing/comments/commentRss/13350.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/testing/services/trackbacks/13350.html</trackback:ping><description><![CDATA[
		<p>
				<font size="2">如果从软盘起动,则Dos引导程序被ROM BIOS直接加载到内存,若从硬盘起动,则被硬盘的 <br />主引导程序加载.不过都是被加载到内存的绝对地址0000:7C00H处.因此,Dos引导程序的第一条指令的地址一定是0000:7C00H. </font>
		</p>
		<p>
				<font size="2">Dos引导程序所做的事情如下: <br />1&gt;调整堆栈位置 <br />2&gt;修改并用修改后的磁盘参数表来复位磁盘系统 <br />3&gt;计算根目录表的首扇区的位置及IO.SYS的扇区位置 <br />4&gt;读入根目录表的首扇区 <br />5&gt;检查根目录表的开头两项是否为IO.SYS及MSDOS.SYS <br />6&gt;将IO.SYS文件开头三个扇区读入内存0000:0700H处 <br />7&gt;跳到0000:0700H处执行IO.SYS,引导完毕 <br />上述每一步若出错,则显示"Non system disk or disk error..."信息,等用户按任一键后试图重新起动. <br />下面的Dos引导程序是从硬盘上得来的,显示MSDOS5.0,但Dos的ver命令报告的是6.22版.FAT表自然是16位的. </font>
		</p>
		<p>
				<font size="2">说明: <br />(DX) 表示寄存器DX的值 <br />逻辑扇区号 以0面0道1扇区作为逻辑0扇区,而不是以Dos引导扇区为逻辑0扇区, <br />当然,对软盘来说二者是相同的,对硬盘则不同 <br />面号 即磁头号 <br />磁道号 即柱面号(对硬盘) <br />物理扇区号 由面号,磁道号,扇区号三者共同指定 </font>
		</p>
		<p>
				<font size="2">偏移 机器码 符号指令 说明 <br />======================================================================== <br />0000 EB3C JMP 003E ;跳过数据区 <br />;以下数据是厂商OEM信息和磁盘BPB表 <br />0000 90 4D 53 44 4F 53-35 2E 30 00 02 08 01 00 .MSDOS5.0..... <br />0010 02 00 02 00 00 F8 CC 00-3F 00 10 00 3F 00 00 00 ........?...?... <br />0020 F1 59 06 00 80 00 29 E3-0B 3F 26 53 4C 4D 20 20 .Y....)..?&amp;SLM <br />0030 20 20 20 20 20 20 46 41-54 31 36 20 20 20 FAT16 <br />------------------------------------------------------------------------ <br />003E FA CLI <br />003F 33C0 XOR AX,AX <br />0041 8ED0 MOV SS,AX <br />0041 8ED0 MOV SS,AX <br />0043 BC007C MOV SP,7C00 ; 初始化堆栈 <br />0046 16 PUSH SS <br />0047 07 POP ES ;(ES)=0000H <br />0048 BB7800 MOV BX,0078 ;1EH 号中断向量的地址为0000:0078H <br />004B 36 SS: ;(SS)=0000H <br />004C C537 LDS SI,[BX] ;取1EH号中断向量的内容存入DS:SI <br />004E 1E PUSH DS ;该中断向量指向一个11字节的磁盘参数表 <br />004F 56 PUSH SI ;取到后压入堆栈中保存 <br />0050 16 PUSH SS <br />0051 53 PUSH BX ;保存地址0000:0078H <br />0052 BF3E7C MOV DI,7C3E ;7C3E-7C00=003EH,即偏移003EH,以下类推 <br />0055 B90B00 MOV CX,000B ;磁盘参数表共11字节  <br />0058 FC CLD <br />0059 F3 REPZ <br />005A A4 MOVSB ;将磁盘参数表复制到0000:7C3EH处 <br />005B 06 PUSH ES <br />005C 1F POP DS ;(DS)=0000H <br />005D C645FE0F MOV BYTE PTR [DI-02],0F ;修改参数表中"磁头定位时间" <br />0061 8B0E187C MOV CX,[7C18] ;从BPB中取"每磁道扇区数" <br />0065 884DF9 MOV [DI-07],CL ;修改参数表中"每磁道扇区数" <br />0068 894702 MOV [BX+02],AX ;(AX)=0000H,修改1EH号中断向量(段址) <br />006B C7073E7C MOV WORD PTR [BX],7C3E ;修改1EH号中断向量(偏移),这样1EH号 <br />006F FB STI ;中断向量的内容为0000:7C3EH,指向新的磁盘参数表 <br />0070 CD13 INT 13 ;用新的磁盘参数表来复位磁盘 <br />0072 7279 JB 00ED ;出错则转出错处理 <br />------------------------------------------------------------------------ <br />; 下面一段程序计算扇区位置 <br />0074 33C0 XOR AX,AX <br />0076 3906137C CMP [7C13],AX ;偏移0013H处是Dos分区的总扇区数 <br />007A 7408 JZ 0084 ;为零表示大硬盘? <br />007C 8B0E137C MOV CX,[7C13] ;不为0则取出来放到偏移0020H处 <br />0080 890E207C MOV [7C20],CX ;这个值本程序未用,似乎为IO.SYS准备的 <br />0084 A0107C MOV AL,[7C10] ;取FAT表的个数 <br />0087 F726167C MUL WORD PTR [7C16] ;乘以一个FAT表所占的扇区数 <br />008B 03061C7C ADD AX,[7C1C] ;加上Dos分区前的扇区数(隐藏扇数,低位) <br />008F 13161E7C ADC DX,[7C1E] ; 高位 <br />0093 03060E7C ADD AX,[7C0E] ;加上Dos分区内的保留扇区数(低位) <br />0097 83D200 ADC DX,+00 ; (高位) <br />009A A3507C MOV [7C50],AX ;根目录表的首扇的逻辑扇区号(低位) <br />009D 8916527C MOV [7C52],DX ; (高位) <br />00A1 A3497C MOV [7C49],AX ;此处放IO.SYS的首扇的逻辑扇区号(低位) <br />00A4 89164B7C MOV [7C4B],DX ; (高位) <br />00A8 B82000 MOV AX,0020 ;根目录表中每项占32字节 <br />00AB F726117C MUL WORD PTR [7C11] ;乘以根目录表中的项数 <br />00AF 8B1E0B7C MOV BX,[7C0B] ;取"每扇区的字节数" <br />00B3 03C3 ADD AX,BX ;这两条指令是为了取整 <br />00B5 48 DEC AX <br />00B6 F7F3 DIV BX ;除以每扇字节数,得到根目录所占扇区数 <br />00B8 0106497C ADD [7C49],AX ;得到根目录表后首扇的逻辑扇区号(低位) <br />00BC 83164B7C00 ADC WORD PTR [7C4B],+00 ; (高位) <br />----------------------------------------------------------------------- <br />;下面一段程序在根目录表中找系统文件IO.SYS和MSDOS.SYS <br />00C1 BB0005 MOV BX,0500 ;内存缓冲区的偏移值 <br />00C4 8B16527C MOV DX,[7C52] ;取根目录表的首扇的逻辑扇区号(高位) <br />00C8 A1507C MOV AX,[7C50] ; (低位) <br />00CB E89200 CALL 0160 ;将逻辑扇区号转换为物理扇区号 <br />00CE 721D JB 00ED ;出错则转出错处理 <br />00D0 B001 MOV AL,01 <br />00D2 E8AC00 CALL 0181 ;读一个扇区到内存(根目录的首扇) <br />00D5 7216 JB 00ED ;出错处理 <br />00D7 8BFB MOV DI,BX ;内存缓冲区的首址 <br />00D9 B90B00 MOV CX,000B ;比较11个字节 <br />00DC BEE67D MOV SI,7DE6 ;偏移01E6处是串"IO SYS",长11字节 <br />00DF F3 REPZ <br />00E0 A6 CMPSB ;看第一项是否为IO.SYS <br />00E1 750A JNZ 00ED ;不是则出错 <br />00E3 8D7F20 LEA DI,[BX+20] ;跳过32字节就指向第二项 <br />00E6 B90B00 MOV CX,000B ;比较11个字节 <br />00E9 F3 REPZ <br />00EA A6 CMPSB ;看第二项是否为MSDOS.SYS <br />00EB 7418 JZ 0105 ;是则两个文件都已找到,跳过出错处理 <br />------------------------------------------------------------------------ <br />;下面一段进行出错处理 <br />00ED BE9E7D MOV SI,7D9E ;偏移019EH处是串"Non system disk..." <br />00F0 E85F00 CALL 0152 ;显示字符串 <br />00F3 33C0 XOR AX,AX <br />00F5 CD16 INT 16 ;等待任一键按下 <br />00F7 5E POP SI <br />00F8 1F POP DS ;得到1EH号中断向量的地址0000:0078H <br />00F9 8F04 POP [SI] <br />00FB 8F4402 POP [SI+02] ;恢复1EH号中断向量的内容 <br />00FE CD19 INT 19 ;自举 <br />0100 58 POP AX <br />0101 58 POP AX <br />0102 58 POP AX ;清理堆栈 <br />0103 EBE8 JMP 00ED ;再次试图起动 <br />------------------------------------------------------------------------ <br />;下面读入IO.SYS的头3个扇区到内存0000:0700H处 <br />0105 8B471A MOV AX,[BX+1A] ;从根目录表第一项中取IO.SYS的首簇号 <br />0108 48 DEC AX <br />0109 48 DEC AX ;首簇号减二 <br />010A 8A1E0D7C MOV BL,[7C0D] ;取每簇的扇区数 <br />010E 32FF XOR BH,BH <br />0110 F7E3 MUL BX ;(首簇号 - 2)乘以 每簇的扇区数 <br />0112 0306497C ADD AX,[7C49] ;相加后得到IO.SYS的首扇的逻辑扇区号 <br />0116 13164B7C ADC DX,[7C4B] <br />011A BB0007 MOV BX,0700 ;内存缓冲区的偏移值 <br />011D B90300 MOV CX,0003 ;循环计数初值,读3个扇区 <br />0120 50 PUSH AX ;逻辑扇区号进栈(低位) <br />0121 52 PUSH DX ; (高位) <br />0122 51 PUSH CX ;循环计数器进栈 <br />0123 E83A00 CALL 0160 ;逻辑扇区号转换为物理扇区号 <br />0126 72D8 JB 0100 ;出错处理 <br />0128 B001 MOV AL,01 <br />012A E85400 CALL 0181 ;读一个扇区到内存缓冲区 <br />012D 59 POP CX ;循环计数出栈 <br />012E 5A POP DX <br />012F 58 POP AX ;逻辑扇区号出栈 <br />0130 72BB JB 00ED ;读盘出错处理 <br />0132 050100 ADD AX,0001 <br />0135 83D200 ADC DX,+00 ;下一个扇区 <br />0138 031E0B7C ADD BX,[7C0B] ;缓冲区指针移动一个扇区的大小 <br />013C E2E2 LOOP 0120 ;循环读入三个扇区 <br />013E 8A2E157C MOV CH,[7C15] ;取"磁盘介质描述",传给IO.SYS <br />0142 8A16247C MOV DL,[7C24] ;取"系统文件所在的驱动器号" <br />0146 8B1E497C MOV BX,[7C49] ;取IO.SYS的首扇的逻辑扇区号 <br />014A A14B7C MOV AX,[7C4B] <br />014D EA00007000 JMP 0070:0000 ;执行IO.SYS,引导完毕 <br />----------------------------------------------------------------------- <br />;显示字符串的子程序 <br />0152 AC LODSB ;从串中取一个字符 <br />0153 0AC0 OR AL,AL <br />0155 7429 JZ 0180 ;为0则已到串尾,返回(共用RET指令) <br />0157 B40E MOV AH,0E <br />0159 BB0700 MOV BX,0007 <br />015C CD10 INT 10 ;显示该字符 <br />015E EBF2 JMP 0152 ;循环显示下一个 <br />----------------------------------------------------------------------- <br />;将逻辑扇区号转换为物理扇区号的子程序 <br />0160 3B16187C CMP DX,[7C18] ;这两条指令是为了避免第二次除法时除数 <br />0164 7319 JNB 017F ;为0 <br />0166 F736187C DIV WORD PTR [7C18] ;逻辑扇取号除以每道扇区数,商(AX)=总磁 <br />016A FEC2 INC DL ;道数,余数(DX)再加一即为扇区号,因为扇 <br />016C 88164F7C MOV [7C4F],DL ;区号是从1开始的,而不是从0开始 <br />0170 33D2 XOR DX,DX <br />0172 F7361A7C DIV WORD PTR [7C1A] ;总磁道数(AX)再除以面数,所得的 <br />0176 8816257C MOV [7C25],DL ;余数(DX)=面号(即磁头号) <br />017A A34D7C MOV [7C4D],AX ;商(AX)=磁道号 <br />017D F8 CLC <br />017E C3 RET ;正常返回 <br />017F F9 STC <br />0180 C3 RET ;异常返回 </font>
		</p>
<img src ="http://www.cppblog.com/testing/aggbug/13350.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/testing/" target="_blank">testing</a> 2006-10-04 20:53 <a href="http://www.cppblog.com/testing/archive/2006/10/04/13350.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>