读取硬盘数据

通过硬盘端口读取

硬盘端口:

0x1f0 ~ 0x1f7 8个端口

读写模式:

  1. CHS
    传入磁头,柱面,扇区信息
  2. LBA
    传入逻辑块起始,读取逻辑块数量

与端口通信:

in dest[al / ax], src[dx / i8] ;从端口读入
out dest[dx / i8], src[al / ax] ;写入端口

选择ax和选择al的差别在于,若端口是8位,则用al,若端口是16位,则用ax

用 LBA28 读取硬盘数据

LBA28是用一个28位的数表示逻辑扇区号的方法,最多可以读取128GB的硬盘

各个端口功能:

0x1f0:16位端口,读取数据的位置

0x1f1:错误寄存器,包含硬盘驱动器最后一次执行命令的状态(错误原因)

0x1f2 ~ 0x1f7:8位端口

0x1f2:要读取的扇区数

0x1f3~0x1f6(低4位):要读取的第一块逻辑扇区号(共28位)

0x1f6(高4位):读取方式设置:标识硬盘号和读写模式

第4位:选择硬盘号(0:主硬盘,1:从硬盘)
第6位:选择读写模式(0:CHS,1:LBA)
(从第0位开始数)

0x1f7:选择写读或写:为0x20时表示读取硬盘,为0x30时表示写硬盘

这部分代码为:

;常量部分
HDDPORT0 equ 0x1f0
HDDREADSET equ 0xe0 ;0b11100000
HDDREADCODE equ 0x20
;变量
StartDiskIndex dd 2 ;
DiskAmount db 1
readHdd:
  ;读取硬盘数量
  mov al, [DiskAmount]
  mov dx, HDDPORT + 2 ;dx = 0x1f2
  out dx, al
  ;写入起始硬盘号前16位
  mov ax, [ReadStart]
  inc dx ;dx = 0x1f3
  out dx, al
  
  mov al, ah
  inc dx ;dx = 0x1f4
  out dx, al
  ;写入硬盘号第17到28位
  mov ax, [ReadStart + 2]
  inc dx ;dx = 0x1f5
  out dx, al
  
  mov al, ah
  mov ah, HDDREADSET ;将硬盘读写模式和读取哪个硬盘整合到al的高4位
  or al, ah
  inc dx ;dx = 0x1f6
  out dx, al
  ;表示要读取硬盘
  mov al, HDDREADCODE
  inc dx ;dx = 0x1f7
  out dx, al

在写入必要的信息后,我们就要等待硬盘给出回复

回复是保存在0x1f7端口的状态码,我们只需要第7位和第3位的信息

第7位为1时,表示硬盘正忙,为0时表示硬盘空闲;第3位为1时表示硬盘已准备好,为0时表示还未准备好

这段代码如下:

  STATECODE equ 0x88 ;0b10001000
  READCODE equ 0x08 ;0b00001000
  .wiats: ;等待
    in al, dx
    and al, STATECODE
    cmp al, READCODE
  jnz .waits

最后从硬盘中读取数据

示例中我要们读取一个完整的扇区,即512字节

我们可以以字节为单位读,也可以以字为单位读

这里用以字为单位读

mov dx, HDDPORT0
mov cx, 256
.readWord:
  in ax, dx
  mov [ds:si], ax ;ds:si为目标内存,换成哪里都可以
  add si, 2
loop .readWord

通过int 13拓展读取硬盘

首先,我们需要一个结构体,它长这样:

DiskAddressPacekt:
    PackSize db 10h
    Reserved db 0
    BlockCount dw 0
    BufferOffset dw 0
    BufferSegment dw 0
    BlockLow dd 0
    BlockHigh dd 0

其中:

PackSize这里固定为16,表示这个包的大小
Reserved表示预留的字节
BlockCount表示将要读取的扇区数
BufferOffset表示目标地址的偏移地址
BufferSegment表示目标地址的段地址
BlockLow表示起始扇区号的前四个字节
BlockHigh表示起始扇区号的后三个字节


我们还需要测试一下,这台机器是不是可以使用int 13扩展

我们这样测试:

.checkInt13:
    mov ah, 41h ;检查用
    mov bx, 55aah
    mov dl, 80h
    int 13h
    cmp bx, 0aa55h
    jnz ErrCatch

如果扩展可用,我们就继续进入读写环节:

.readDisk:
    mov ah, 42h ;读取用
    mov dl, 80h
    mov si, DiskAddressPacekt
    int 13h
    test ah, ah
    jnz ErrCatch

.writeDisk:
    mov ah, 43h ;写入用
    mov dl, 80h
    mov si, DiskAddressPacekt
    int 13h
    test ah, ah
    jnz ErrCatch

如果正确读写数据,就可以继续执行,如果出现错误,可以和前面的错误一起写一个错误处理

posted @ 2022-03-21 13:06  Nomaldisk  阅读(783)  评论(0编辑  收藏  举报