0xAA55 发表于 2014-1-26 20:52:14

【硬件】软盘的存储结构与读取

虽然现在软盘早已被淘汰(小时候用过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被写入了
mov cx,FLP_SECPERTRACK    ;循环写入每个扇区
  .LoopSec:
push cx           ;此时的cx被写入了
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,
  mov cl,FLP_SECPERTRACK+1
  sub cl,
  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,
  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



页: [1]
查看完整版本: 【硬件】软盘的存储结构与读取