1. 程式人生 > >軟盤結構 磁頭號和起始扇區的計算方法

軟盤結構 磁頭號和起始扇區的計算方法

               

軟盤結構(磁頭號和起始扇區的計算方法)

刺蝟@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

不好意思,沒寫註釋,不過有了上面的解釋,我想這段程式碼應該是很好懂得~~


自己動手寫作業系統》讀書筆記系列