软盘结构(磁头号和起始扇区的计算方法)

 

软盘结构(磁头号和起始扇区的计算方法)

刺猬@http://blog.csdn.net/littlehedgehog

; ----------------------------------------------------------------------------
;
 函数名: ReadSector
;
----------------------------------------------------------------------------
;
 作用:
;
    从第 ax 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中
ReadSector:
    
;  -----------------------------------------------------------------------
     ;  怎样由扇区号求扇区在磁盘中的位置 (扇区号 -> 柱面号, 起始扇区, 磁头号)
     ;  -----------------------------------------------------------------------
     ;  设扇区号为 x
     ;                            ┌ 柱面号 = y >> 1
     ;        x           ┌ 商 y ┤
     ;  -------------- => ┤      └ 磁头号 = y & 1
     ;   每磁道扇区数     │
     ;                    └ 余 z => 起始扇区号 = z + 1
    push    bp
    mov    bp
,  sp
    sub    esp
,   2              ;  辟出两个字节的堆栈区域保存要读的扇区数: byte [bp-2]

    mov    byte 
[ bp-2 ] ,  cl
    push    bx            
;  保存 bx
    mov    bl ,   [ BPB_SecPerTrk ]      ;  bl: 除数
    div    bl             ;  y 在 al 中, z 在 ah 中
    inc    ah             ;  z ++
    mov    cl ,  ah             ;  cl <- 起始扇区号
    mov    dh ,  al             ;  dh <- y
    shr    al ,   1              ;  y >> 1 (其实是 y/BPB_NumHeads, 这里BPB_NumHeads=2)
    mov    ch ,  al             ;  ch <- 柱面号
    and    dh ,   1              ;  dh & 1 = 磁头号
    pop    bx             ;  恢复 bx
     ;  至此, "柱面号, 起始扇区, 磁头号" 全部得到 ^^^^^^^^^^^^^^^^^^^^^^^^
    mov    dl ,   [ BS_DrvNum ]          ;  驱动器号 (0 表示 A 盘)
.GoOnReading:
    mov    ah
,   2              ;  读
    mov    al ,  byte  [ bp-2 ]          ;  读 al 个扇区
    int    13h
    jc    .GoOnReading        
;  如果读取错误 CF 会被置为 1, 这时就不停地读, 直到正确为止

    add    esp
,   2
    pop    bp

    ret

 

于渊 关于软盘结构的这段笔墨惜得不是地方 ,其实很多看这种入门级书的读者对于软盘(磁盘)的结构认识大多都是不到位的。我在阅读这段代码时也费了不少周折,最后发现其实是我对软盘结构认识不足,补上这一课,这段代码就好读多了。

3.5寸1.44M软盘结构

1、 结构:2面、80道/面、18扇区/道、512字节/扇区
         扇区总数=2面 X  80道/面 X  18扇区/道  =  2880扇区
         存储容量= 512字节/扇区X  2880扇区 =  1440 KB

 2、  2  面: 编号0----1;
          80道: 编号0----79 ;
         18扇区:编号1----18 ;

这个很多书都有介绍,恕不细表。下面来看看软盘中磁道的安排,这会使我们感到很诧异——原来软盘结构安排会是这样。

3、相对扇区号:共2880个扇区,相对扇区号范围为 0----2879

编号顺序:
扇区物理号               相对扇区号
0面,0道,1扇区             0
0面,0道,2扇区             1
0面,0道,3扇区             2
…………………….
0面,0道,18扇区           17
1面,0道,1扇区            18
……………
1面,0道,18扇区           35
0面,1道,1扇区            36
0面,1道,18扇区           53
1面,1道,1扇区            54
………

注意下红色字,它表明软盘的排列并不是按照我们所想象的"把0面先排完了再开始排1面,而是交替排列的"

 4、物理扇区号(A,B,C)与相对扇区号(S)相互转换公式:
头/面(0--1)      道(0-79)       扇区 (1--18) 
 A                       B                      C

例如:A=1面          B= 15道       C=7扇区  这就是它的物理扇区号,现在进入关键问题——如何计算相对扇区呢?


计算相对扇区时,参照上面的软盘结构排列表。我们应该清楚在15道之前,即0~14道里面,每道都有有18个扇区,而又0、1两面都有磁道,故而在0~14道有(0道----14道)*2面*18, 在计算第15道时,注意下我们要计算的15道是在1面,而1面之前的0面15道,有18个扇区,而在1面的15道磁道中,有7个扇区。一共有0面的第15道18个扇区+1面第15道7个扇区-1,所以上述例子中的相对扇区号是(0道----14道)*2面*18+0面的第15道18个扇区+1面第15道7个扇区-1

有了上面的叙述,源代码中除以18求出来商就是磁道数,而余数即是扇区数目,由于除以了18,那么前面的结构表就可以如下表示:

0面,0道
1面,0道
0面,1道
1面,1道
0面,2道
1面,2道
.......
0面,12道
1面,12道

磁道除以2表示当前物理磁道号(因为是交替排列的!注意看上表的结构),而余数就可以表示磁头号。

 

于渊代码中间很多都是直接在寄存器中反复玩弄汇编技巧,这段程序让我看得相当郁闷~  自己改写了一个,里面用内存保留计算结果,这样清晰很多:

以下是变量定义:

dbTrackNum  db 0 ;磁道数
dbSectorNum  db 0 ;扇区数
dbdriverNum  db 0 ;驱动器号
dbResistiveNum  db 0 ;磁头数

 

ReadSector:
    push    dx
    push    bx
    

    mov    bl,[BPB_SecPerTrk]
    div    bl
    inc    ah
    mov    
byte  [dbSectorNum],ah
    mov    ah,al
    shr    al,
1
    mov    
byte  [dbTrackNum],al
    and    ah,1b
    mov    
byte  [dbResistiveNum],ah
    
    mov    ah,2h
    mov    al,cl
    mov    dl,[dbdriverNum]
    mov    dh,[dbResistiveNum]
    mov    ch,[dbTrackNum]
    mov    cl,[dbSectorNum]

    pop    bx

.Reading:
    
int     13h
jc    .Reading

    pop    dx
    ret

 

 

 

不好意思,没写注释,不过有了上面的解释,我想这段代码应该是很好懂得~~

 


自己动手写操作系统》读书笔记系列

 

你可能感兴趣的:(Operating,System,Masm&Nasm)