Chinaunix首页 | 论坛 | 博客
  • 博客访问: 656666
  • 博文数量: 171
  • 博客积分: 2246
  • 博客等级: 大尉
  • 技术积分: 1574
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-31 11:45
文章分类

全部博文(171)

文章存档

2018年(3)

2017年(4)

2015年(1)

2014年(20)

2013年(57)

2012年(86)

分类: LINUX

2012-12-20 13:48:09


  1. ;----------------------------------------------------------------------------
  2. ; 函数名: ReadSector
  3. ;----------------------------------------------------------------------------
  4. ; 作用:
  5. ; 从第 ax 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中
  6. ReadSector:
  7. ; -----------------------------------------------------------------------
  8. ; 怎样由扇区号求扇区在磁盘中的位置 (扇区号 -> 柱面号, 起始扇区, 磁头号)
  9. ; -----------------------------------------------------------------------
  10. ; 设扇区号为 x
  11. ;                             ┌ 柱面号 = y >> 1
  12. ; x                  ┌ 商 y  ┤
  13. ; -------------- =>  ┤       └ 磁头号 = y & 1
  14. ; 每磁道扇区数         |
  15. ;                    └ 余 z => 起始扇区号 = z + 1

  16. push bp
  17. mov bp, sp
  18. sub esp, 2   ; 辟出两个字节的堆栈区域保存要读的扇区数: byte [bp-2]

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

  37. add esp, 2
  38. pop bp

  39. ret

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

3.5寸1.44M软盘结构

 1、 结构:2面、80道/面、18扇区/道、512字节/扇区
          扇区总数 = 2面 * 80道/面 * 18扇区/道  =  2880扇区
          存储容量 = 512字节/扇区 * 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道
0面,0道,18扇区     17
1面,0道,1扇区      18
……………………     ...      1面,0道
1面,0道,18扇区     35   
0面,1道,1扇区      36 

……………………     ...      0面,1道
0面,1道,18扇区     53
1面,1道,1扇区      54      
……………………              1面,1道

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

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

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

计算相对扇区时,参照上面的软盘结构排列表。例如:如果我们要计算1面15道第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表示当前物理磁道号(因为是交替排列的!注意看上表的结构),而余数就可以表示磁头号。

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

  1. dbTrackNum     db 0 ;磁道数
  2. dbSectorNum    db 0 ;扇区数
  3. dbdriverNum    db 0 ;驱动器号
  4. dbResistiveNum db 0 ;磁头数

  5. ReadSector:
  6. push dx
  7. push bx

  8. mov bl,[BPB_SecPerTrk]
  9. div bl
  10. inc ah
  11. mov byte [dbSectorNum],ah
  12. mov ah,al
  13. shr al,1
  14. mov byte [dbTrackNum],al
  15. and ah,1b
  16. mov byte [dbResistiveNum],ah
  17. mov ah,2h
  18. mov al,cl
  19. mov dl,[dbdriverNum]
  20. mov dh,[dbResistiveNum]
  21. mov ch,[dbTrackNum]
  22. mov cl,[dbSectorNum]
  23. pop bx
  24. .Reading:
  25. int 13h
  26. jc .Reading
  27. pop dx
  28. ret
From:http://blog.csdn.net/littlehedgehog/article/details/2147361

阅读(1407) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~