转自:http://blog.csdn.net/chl290115231/article/details/50904636
在《30天自制操作系统》中,作者使用软盘作为操作系统存储介质进行操作系统的编写讲解。但目前计算机设备都已基本放弃软盘支持,虽然依然可以在虚拟机上进行模拟练习,始终还是希望有一个可以真正能在物理设备上驱动安装的系统。
目前常用的移动介质基本都是U盘,所以我开始尝试用U盘开始学习。但在进行存储读写时,就出现了问题。因为U盘的存储结构和软盘是有区别的。而且,现在多数都使用FAT32格式,那么对于MBR中BPB(BIOS Parameter Block)的结构也存在差异。
目前对于磁盘的读写有2种方式,一种是CHS寻址模式,一种是LBA寻址模式。CHS方式更多的是基于最初的磁盘结构,就是柱面+磁头+扇区的读写方式。书中作者对软盘的读写就是采用的这种方式。LBA是一种基于逻辑地址块的寻址模式。这种模式隐藏了存储器底层的一些细节,比如对于柱面、磁头、扇区等的了解。因而也是一种更为通用的磁盘读写模式。虽然CHS和LBA的寻址基本单位都是扇区,但CHS需要3个参数同时确定一个扇区,而LBA将所有的扇区进行逻辑上的线性排列,从而能够进行线性查询。
BOIS中的INT13H函数支持这两种寻址模式。
在查找资料的过程中,我没有查找到利用INT13H函数用CHS模式对U盘进行读写的示例,因为我也是初学者,对于这方面的知识也不全面,所以,我也不确定在CHS模式是否可以。但LBA模式是一定可以的。
LBA模式在读写硬盘上虽然较为CHS模式简单,因为它是线性寻址的。但在INT13H函数中,需要提前设置一个地址数据结构,用于存储一些读取信息,比如读取的内存地址、扇区数、其实LBA块等。该数据结构的构成格式如下:
偏移(字节)
|
大小(字节)
|
说明
|
0
|
1
|
该数据结构的大小,通常为16字节
|
1
|
1
|
通常为0,意义不明
|
2
|
2
|
传输的扇区数(在某些BIOS中最大为127)。
|
4
|
4
|
内存地址(2字节的段地址:2字节的偏移地址)。
|
8
|
4
|
起始LBA块
|
12
|
4
|
用于对大容量存储设备的读取
|
该模式下的INT13H调用过程:
l 首先在磁盘地址数据结构体中设置正确的值。
l 设置DS:SI地址数据结构在内存中的地址
l 读出数据到内存:AH=0x42,写入内存数据到磁盘AH=0x43
l DL=驱动器编号
l 调用INT 0x13
在读取的过程中出现错误的话,进位标志(carry flag)会被置1。执行成功的话,AH置0。
实例:
-
entry:
-
movax,cs;初始化寄存器
-
movds,ax
-
movds,ax
-
moves,ax
-
-
movah,0x42
-
movdl,0x80
-
movsi,packet
-
int0x13
-
-
jcerror
-
-
;将写入的内存地址后移512字节
-
;以下是将地址数据结构中的起始LBA后移1块继续写入下一个扇区
-
-
;将packet的内存偏移512字节
-
movax,[bufferoff]
-
movbx,bufferoff
-
addax,0x0200
-
mov[bx],ax
-
-
;将起始LBA加1,以读取下一个扇区
-
movax,[blockNum]
-
movbx,blockNum
-
addax,1
-
mov[bx],ax
-
-
cmpax,5;连续读取4个扇区
-
jefinish
-
-
jmpentry
-
;地址数据结构体
-
packet:
-
packet_size:db10h;packet大小,16个字节
-
reserved:db0
-
count:dw1;读1个扇区
-
bufferoff:dw0x0820;读到内存0x0820处,偏移地址
-
bufferseg:dw0;段地址
-
blockNum:dd1;起始LBA块
-
dd0
-
-
error:
-
finish:
对于以上程序,也可以在packet的count中一次性设置需要写入的扇区数。但为了测试连续写入,所以我每次只写入一个扇区。
详细的可参见:
http://wiki.osdev.org/ATA_in_x86_RealMode_(BIOS)
http://www.cnblogs.com/zeng2013/p/3637864.html
|