| 
UID1精华积分77054威望 点宅币 个贡献 次宅之契约 份最后登录1970-1-1在线时间 小时 
 | 
 
| 虽然现在软盘早已被淘汰(小时候用过3.5英寸软盘的同学们请举手!DOS时代1.44 MB的容量实在不敢恭维),但是从软盘开始学习操作系统编程确实很有帮助。特别是虚拟机,对于虚拟机,软盘是相当方便的工具。现在我来讲讲软盘的读写。 在这里,我只说怎么用16位BIOS中断读取软盘数据,我并不打算说如何直接IO读取软盘数据。如果你是来找软盘IO读取方式的请绕行。但是,此贴在后面会说道软盘数据的分布方式和CHS寻址的问题,请留意。
 首先就是读取问题,很简单,调用BIOS中断INT 0x13 AH=0x02为CHS方式读取磁盘功能,INT 0x13 AH=0x03为CHS方式写入磁盘功能。现在我们来详细说明一下它们的用法。
 
 AH=功能号(0x02、0x03)
 AL=要读取的扇区数量
 CX=磁道号和扇区号,其中磁道号为CL的高2位和CH组成,扇区号为CL的低6位。扇区号是从1开始的数字。
 DH=磁头号
 DL=驱动器号(小于0x80的为软驱号,大于、等于0x80的为硬盘号)
 ES:BX=缓冲区地址
 
 详情请见以下网址:
 CHS方式读取:http://www.ctyme.com/intr/rb-0607.htm
 CHS方式写入:http://www.ctyme.com/intr/rb-0608.htm
 
 下面来讲一下CHS寻址的问题。软盘的扇区是按照什么样的顺序排列的,特别是软盘镜像文件中的“扇区”是怎么分布的,这是一个问题。
 它是先排列一整个盘面,然后换一个盘面排列,还是两个盘面交替排列?
 我们可以亲自做个实验来解决这个问题。
 
 实验工具:
 Microsoft Virtual PC 2007 32位(虚拟机)NASM(编译器)
 记事本
 WinHex(查看文件的工具)
 
 我们的思路是让虚拟机从软盘引导,软盘的引导扇区是我们编写好的指令,指令的作用是按照我们设想好的排序方式写软盘,给每个扇区写入一个“索引数字”。然后用WinHex打开软盘,查看索引数字的排序方式,以此来判断软盘的排序方式。
 首先我们需要一个引导程序,看!代码如下
 
 org 0x7C00
 bits 16
 
 %define FLP_SECPERTRACK   18
 %define FLP_TRACKPERHEAD   80
 %define FLP_HEADPERDISK   2
 
 Start:
 mov ax,cs
 mov es,ax
 mov ss,ax
 mov ds,ax          ;对齐各个用到的段,包括栈段
 mov sp,Start         ;栈指向Start处
 mov bp,sp          ;借助bp访问栈
 xor si,si          ;si被用作“扇区索引号”
 
 
 mov cx,FLP_TRACKPERHEAD   ;循环写入每个盘面
 .LoopCyl:
 push cx           ;此时的cx被写入了[bp-2]
 mov cx,FLP_SECPERTRACK    ;循环写入每个扇区
 .LoopSec:
 push cx           ;此时的cx被写入了[bp-4]
 mov bx,0x600         ;0:0x600是缓冲区
 mov di,bx
 mov ax,si
 mov cx,0x100
 rep stosw          ;把正面的扇区编号写入缓冲区
 add ax,FLP_SECPERTRACK*FLP_TRACKPERHEAD
 mov cx,0x100
 rep stosw          ;再把背面的扇区编号写入缓冲区
 
 
 mov ax,0x0301        ;写入正面的扇区
 mov ch,FLP_TRACKPERHEAD
 sub ch,[bp-2]
 mov cl,FLP_SECPERTRACK+1
 sub cl,[bp-4]
 mov dx,0x0000
 int 0x13
 
 mov ax,0x0301        ;再写入背面的扇区
 inc dh
 add bx,0x200
 int 0x13
 
 inc si            ;扇区索引号+1
 pop cx
 loop .LoopSec        ;循环写入磁道的每一个扇区
 mov ah,0x0E         ;每写入一个正反面磁道,打印一个字符
 mov al,[bp-2]
 mov dx,0x0007
 int 0x10
 pop cx
 loop .LoopCyl        ;循环写入盘面的每一个磁道
 
 mov ax,0x0E01        ;最后打印一个笑脸,表示结束
 mov dx,0x000F
 int 0x10
 
 cli             ;当机
 hlt
 
 times 510-($-$$) nop     ;填充剩余字节
 dw 0xAA55
 
 ;填充字节,使这个文件的大小正好等于一个软盘的大小。
 times (FLP_SECPERTRACK*FLP_TRACKPERHEAD*FLP_HEADPERDISK*0x100)-0x100 dw 0
 
 哟西,这样就行了。保存为ShowFlp.asm。让我们运行NASM开始编译:
 NASM ShowFlp.asm -o ShowFlp.img
 嗯,NASM没有报错,现在要做的是启动虚拟机,让虚拟机以这个文件为软盘镜像引导。
 送:ShowFlp.7z
 
 感谢我吧。
 然后呢,运行VM,设置新的虚拟机,操作系统为“其它”,内存不必太大,1 MB足够了。虚拟硬盘可有可无,以后如果要用的话设置个256 MB的,运行个DOS没问题了。
 运行虚拟机,把虚拟机的软驱设置为“捕获软驱镜像文件”(Capture Floppy Image File),把我们刚才生成的ShowFlp.img弄进去,然后重启虚拟机。
 看!虚拟机运行啦!我们预测的结果,是它在屏幕上打印一些奇怪的字符(中途会“嘀~”叫一声),然后显示一个笑脸字符“☺”,退出程序。
 
   
 他果然按照预想的运行了!那么我们让它释放软盘镜像文件,然后用WinHex打开它!
 
   
 果然,软驱的前几个扇区都是按照我们给的索引排序的。
 那么我们来看看在第18扇区处的情况:
 
   
 咦?居然是0x05A0(也就是1440)。 1440?这不是一个盘面的扇区量吗?
 果然呢,软盘的存储方式是两磁头之间交替存储的呢。我们来总结一下。
 软盘的存储,是每个磁道中的扇区是连续存储的,但是磁头是交替存储的,也就是说,最小单位是扇区,其次是磁头,最后是磁道。
 这也是为什么磁道要被称作“柱面”的原因了。
 最后给一个处理后的软盘镜像文件,望笑纳。
 After.7z
 
 
 
 
 | 
 |