问题
我想从硬盘里引导启动,但将一些数据放在了USB-HDD(U盘做成的)里,需要读取。我的物理机上有两块固定硬盘,加上U盘总的也就三块,按理来说直接调用int 13h 8x(8x为U盘模拟成的HDD的驱动器号)就可以直接读取了,但是读取不到(从80-85H都试过了)。由于这方面的资料太少,索性记录一下
利用CHS方式读取数据
这种方式资料比较充足,就不记录了
利用LBA方式读取数据(推荐)
查阅维基百科后发现,13h号中断中提供了LBA方式来读写磁盘。
具体描述为:
就是说 13h 中断还提供了扩展功能号就比如 41h、42h、43h~46h,但是需要设置磁盘地址数据包(disk address packet),由 ds:si来指向。
具体调用方式为:
1 | 入口参数: |
地址数据包的x86汇编实现
1 | buffer: |
详细说明
一、接口及错误码
在扩展 Int13H 调用中一般使用如下寄存器约定:ds:si ==> 磁盘地址数据包( disk address packet ) dl ==> 驱动器号 ah ==> 功能代码 / 返回码 在基本 Int13H 调用中 ,
0 - 0x7F 之间的驱动器号代表可移动驱动器 ;
0x80 - 0xFF 之间的驱动器号代表固定驱动器。
但在扩展 Int13H 调用中 0x80 - 0xFF 之间还包括一些新出现的可移动驱动器, 比如活动硬盘等。 这些驱动器支持先进的锁定,解锁等功能。
ah 返回的错误码除了标准 Int13H 调用规定的基本错误码以外,又 增加 了以下错误码:
B0h 驱动器中的介质 未被锁定
B1h 驱动器中的介质已经锁定 B2h 介质是可移动的
B3h 介质正在被使用
B4h 锁定记数溢出
B5h 合法的弹出请求失败
二、API 中断子集 1.X版的扩展 Int13H 调用中规定了两个主要的 API 子集。
第一个子集提供了访问大硬盘所必须的功能, 包括 检查扩展 In13H 是否存在( 41h ), 扩展读( 42h ), 扩展写( 43h ), 校验扇区( 44h ), 扩展定位( 47h ) 和 取得驱动器参数 ( 48h ).
第二个子集提供了对软件控制驱动器锁定和弹出的支持, 包括 检查扩展 Int13H 是否存在( 41h ), 锁定/解锁驱动器( 45h ), 弹出驱动器( 46h ), 取得驱动器参数( 48h ), 取得扩展驱动器改变状态( 4Arrayh ), int 15h。 如果使用了调用规范中不支持的功能 , BIOS 将返回: 错误码 ah = 01h ;CF = 1。
三、子集介绍 (一)
41H 检验扩展功能是否存在
入口:AH = 41h ;BX = 55AAh ;DL = 驱动器号
支持返回:CF = 0; BX = AA55h AH = 扩展功能的主版本号;AL = 内部使用 /副版本号 CX = API 子集支持位图
不支持返回:CF = 1;AH = 错误码 01h, 无效命令
说明:这个调用检验对特定的驱动器是否存在扩展功能。如果进位标 志(CF)置1 则此驱动器不支持扩展功能;如果进位标志(CF)为 0, 同时BX = AA55h, 则 存在扩展功能;此时 CX 的 0 位表示是否支持第一个子集, 1位表示是否 支持第二个子集。 对于 1.x 版的扩展 Int13H 来说, 主版本号 AH = 1。AL 是副版本号, 但这仅限于 BIOS 内部使用 , 任何软件不得检查 AL 的值。
*42H 扩展读 *
入口: AH = 42h;DL = 驱动器号;DS:DI = 磁盘地址数据包 (Disk Address Packet) # 数据结构中有(FAT32好像用ES:SI传输)
成功返回:CF = 0, AH = 0
失败返回:CF = 1, AH = 错误码
43H 扩展写
入口:AH = 43h ; AL 0 位 = 0 关闭写校验 /1 打开写校验 ;1 - 7 位保留, 置 0 ; DL = 驱动器号;DS:DI = 磁盘地址数据包(DAP格式如上)
成功返回:CF = 0, AH = 0
失败返回:CF = 1, AH = 错误码
44H 校验扇区
入口:AH = 44h;DL = 驱动器号;DS:DI = 磁盘地址数据包(DAP)
成功返回: CF = 0, AH = 0
失败返回:CF = 1, AH = 错误码
这个调用校验磁盘数据, 但并不将数据读入内存。如果出现错误 , DAP 的“扇区数”项中则记录了出错前实际读取的数据块个数。
46H 弹出可移动驱动器中的介质
入口:AH = 46h ;AL = 0 保留 ;DL = 驱动器号
成功返回: CF = 0, AH = 0
失败返回:CF = 1, AH = 错误码
说明:这个调用用来弹出指定的可移动驱动器中的介质。 所有标号大于等于 0x80 的可移动驱动器必须支持这个功能。如果 在支持可移动驱动器控制功能子集的固定驱动器上使用这个功能调用, 将 会返回错误码 AH = B2h (介质不可移动) 。如果试图弹出一个被锁定的介质 将返回错误码 AH = B1h (介质被锁定)。 如果试图弹出一个没有介质的驱动器, 则返回错误码 Ah = 31h ( 驱动器 中没有介质) 。如果试图弹出一个未锁定的可移动驱动器中的介质, Int13h会调用 Int15h (AH = 52h) 来检查弹出请求能否执行。如果弹出请求被拒绝则返回错误码(同 Int15h)。如果弹出请求被接受,但出现了其他错误, 则返回错误码 AH = B5h。
47H 扩展定位
入口:AH = 47h ;DL = 驱动器号;DS:DI = 磁盘地址数据包(DAP)
成功返回: CF = 0, AH = 0
失败返回:CF = 1, AH = 错误码 这个调用将磁头定位到指定扇区
48H 取得驱动器参数
入口:AH = 48h ;DL = 驱动器号 ;DS:DI = 返回数据缓冲区地址
成功返回: CF = 0, AH = 0 DS:DI 驱动器参数数据包地址(Drive Parameters Packet 参见后面)
失败返回:CF = 1, AH = 错误码
这个调用返回指定驱动器的参数