讀取硬盤數據


通過硬盤端口讀取

硬盤端口:

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

如果正確讀寫數據,就可以繼續執行,如果出現錯誤,可以和前面的錯誤一起寫一個錯誤處理


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM