读取磁盘:LBA方式
LBA简介
磁盘读取发展
IO操作读取硬盘的三种方式:
chs方式 :小于8G (8064MB)
LBA28方式:小于137GB
LBA48方式:小于144,000,000 GB
LBA方式访问使用了data寄存器,LBA寄存器(总共3个),device寄存器,command寄存器来完成的。
LBA28和LBA48方式:
LBA28方式使用28位来描述一个扇区地址,最大支持128GB的硬磁盘容量。
LBA28的寄存器
| 寄存器 | 端口 | 作用 |
|---|---|---|
| data寄存器 | 0x1F0 | 已经读取或写入的数据,大小为两个字节(16位数据) 每次读取1个word,反复循环,直到读完所有数据 |
| features寄存器 | 0x1F1 | 读取时的错误信息 写入时的额外参数 |
| sector count寄存器 | 0x1F2 | 指定读取或写入的扇区数 |
| LBA low寄存器 | 0x1F3 | lba地址的低8位 |
| LBA mid寄存器 | 0x1F4 | lba地址的中8位 |
| LBA high寄存器 | 0x1F5 | lba地址的高8位 |
| device寄存器 | 0x1F6 | lba地址的前4位(占用device寄存器的低4位) 主盘值为0(占用device寄存器的第5位) 第6位值为1 LBA模式为1,CHS模式为0(占用device寄存器的第7位) 第8位值为1 |
| command寄存器 | 0x1F7 | 读取,写入的命令,返回磁盘状态 1 读取扇区:0x20 写入扇区:0x30 磁盘识别:0xEC |
IDE通道1,读写0x1f0-0x1f7号端口
IDE通道2,读写0x170-0x17f号端口
CHS方式:
写0x1f1: 0
写0x1f2: 要读的扇区数
写0x1f3: 扇区号W
写0x1f4: 柱面的低8位
写0x1f5: 柱面的高8位
写0x1f6: 75位,101,第4位0表示主盘,1表示从盘,30位,磁头号
写0x1f7: 0x20为读, 0x30为写
读0x1f7: 第4位为0表示读写完成,否则要一直循环等待
读0x1f0: 每次读取1个word,反复循环,直到读完所有数据
24-bit LBA方式:
写0x1f1: 0
写0x1f2: 要读的扇区数
写0x1f3: LBA参数的0~7位
写0x1f4: LBA参数的8~15位
写0x1f5: LBA参数的16~23位
写0x1f6: 75位,111,第4位0表示主盘,1表示从盘,30位,LBA参数的24~27位
写0x1f7: 0x20为读, 0x30为写
读0x1f7: 第4位为0表示读写完成,否则要一直循环等待
读0x1f0: 每次读取1个word,反复循环,直到读完所有数据
48-bit LBA方式:
写两次0x1f1端口: 0
写两次0x1f2端口: 第一次要读的扇区数的高8位,第二次低8位
写0x1f3: LBA参数的24~31位
写0x1f3: LBA参数的0~7位
写0x1f4: LBA参数的32~39位
写0x1f4: LBA参数的8~15位
写0x1f5: LBA参数的40~47位
写0x1f5: LBA参数的16~23位
写0x1f6: 75位,010,第4位0表示主盘,1表示从盘,30位,0
写0x1f7: 0x24为读, 0x34为写
LBA和CHS的的对应关系
虽然LBA和CHS的两种定位方式不同,但其实两者间还是有一个转换关系的。
读取硬盘
1)sector count寄存器寄存器写入读取的扇区数
2)LBA low寄存器,LBA mid寄存器,LBA high寄存器写入lba地址
3)device寄存器写入lba地址和读取模式
4)command寄存器写入写入命令
5)读取两个字节数据,多次循环直到读取完扇区数据。
代码
boot.asm
引导文件,初始化屏幕后,读取硬盘并加载4个扇区到内存位置[0x90000]处。然后跳转到0x90000处执行指令。
;Rats OS
;Tab=4
[bits 16]
org 0x7c00 ;指明程序的偏移的基地址
;----------- loader const ------------------
LOADER_SECTOR_LBA equ 0x1 ;第2个逻辑扇区开始
LOADER_SECTOR_COUNT equ 9 ;读取9个扇区
LOADER_BASE_ADDR equ 0x9000 ;内存地址0x9000
;-------------------------------------------
;引导扇区代码
jmp Entry
db 0x90
db "RATSBOOT" ;启动区的名称可以是任意的字符串(8字节)
;程序核心内容
Entry:
;------------------
;初始化寄存器
mov ax,0
mov ss,ax
mov ds,ax
mov es,ax
mov ss,ax
mov fs,ax
mov gs,ax
mov sp,0x7c00
;------------------
;清屏
mov ah,0x06 ;清除屏幕
mov al,0
mov cx,0
mov dx,0xffff
mov bh,0x17 ;属性为蓝底白字
int 0x10
mov ah,0x02 ;光标位置初始化
mov dx,0
mov bh,0
mov dh,0x0
mov dl,0x0
int 0x10
;------------------
;读取硬盘1-10扇区
mov ebx,LOADER_SECTOR_LBA ;LBA扇区号
mov cx,LOADER_SECTOR_COUNT ;读取扇区数
mov di,LOADER_BASE_ADDR ;写入内存地址
call Func_ReadLBA16
jmp LOADER_BASE_ADDR
; ------------------------------------------------------------------------
; 读取磁盘:Func_ReadLBA16
; 参数:
; ebx 扇区逻辑号
; cx 读入的扇区数,8位
; di 读取后的写入内存地址
; ------------------------------------------------------------------------
Func_ReadLBA16:
;设置读取的扇区数
mov al,cl
mov dx,0x1F2
out dx,al
;设置lba地址
;设置低8位
mov al,bl
mov dx,0x1F3
out dx,al
;设置中8位
shr ebx,8
mov al,bl
mov dx,0x1F4
out dx,al
;设置高8位
shr ebx,8
mov al,bl
mov dx,0x1F5
out dx,al
;设置高4位和device
shr ebx,8
and bl,0x0F
or bl,0xE0
mov al,bl
mov dx,0x1F6
out dx,al
;设置commond
mov al,0x20
mov dx,0x1F7
out dx,al
.check_status:;检查磁盘状态
nop
in al,dx
and al,0x88 ;第4位为1表示硬盘准备好数据传输,第7位为1表示硬盘忙
cmp al,0x08
jnz .check_status ;磁盘数据没准备好,继续循环检查
;设置循环次数到cx
mov ax,cx ;乘法ax存放目标操作数
mov dx,256
mul dx
mov cx,ax ;循环次数 = 扇区数 x 512 / 2
mov bx,di
mov dx,0x1F0
.read_data:
in ax,dx ;读取数据
mov [bx],ax ;复制数据到内存
add bx,2 ;读取完成,内存地址后移2个字节
loop .read_data
ret
FillSector:
resb 510-($-$$) ;处理当前行$至结束(1FE)的填充
db 0x55, 0xaa
loader.asm
被引导扇区加载到0x90000位置,执行输出hello in loader文字
;Rats OS
;Tab=4
[bits 16]
section loader vstart=LOADER_BASE_ADDR ;指明程序的偏移的基地址
;----------- loader const ------------------
LOADER_BASE_ADDR equ 0x9000 ;内存地址0x9000
;---------------------------------------
jmp Entry
;程序核心内容
Entry:
;---------------------------
;输出字符串
mov si,HelloMsg ;将HelloMsg的地址放入si
mov dh,0 ;设置显示行
mov dl,0 ;设置显示列
call Func_Sprint ;调用函数
jmp $ ;让CPU挂起,等待指令
; ------------------------------------------------------------------------
; 显示字符串函数:Func_Sprint
; 参数:
; si = 字符串开始地址,
; dh = 第N行,0开始
; dl = 第N列,0开始
; ------------------------------------------------------------------------
Func_Sprint:
mov cx,0 ;BIOS中断参数:显示字符串长度
mov bx,si
.len:;获取字符串长度
mov al,[bx] ;读取1个字节到al
inc bx ;读取下个字节
cmp al,0 ;是否以0结束
je .sprint
inc cx ;计数器
jmp .len
.sprint:;显示字符串
mov bx,si
mov bp,bx
mov bx,ds
mov es,bx ;BIOS中断参数:计算[ES:BP]为显示字符串开始地址
mov ah,0x13 ;BIOS中断参数:中断模式
mov al,0x01 ;BIOS中断参数:输出方式
mov bh,0x0 ;BIOS中断参数:指定分页为0
mov bl,0x1F ;BIOS中断参数:显示属性,指定白色文字
int 0x10 ;调用BIOS中断操作显卡。输出字符串
ret
; ------------------------------------------------------------------------
;准备显示字符串
HelloMsg: db "hello in loader!",0
times 512-($-$$) db 0 ; 处理当前行$至结束(1FE)的填充
运行
创建Makefile文件,并执行make命令
# tools
PLATFORM=Linux
NASM=nasm
QEMU=qemu-system-x86_64
QEMU-IMG=qemu-img
BOCHS=bochs
BX-IMG=bximage
# args
boot=boot
build=build
target: prepare img
$(BOCHS) -f bochsrc.me
img: $(build)/ratsos.img
@echo "build img completed"
$(build)/ratsos.img:$(build)/boot.bin $(build)/loader.bin
$(BX-IMG) -hd -mode=flat -size=32 -q $(build)/ratsos.img
sleep 1
dd if=$(build)/boot.bin of=$(build)/ratsos.img bs=512 count=1 conv=notrunc
dd if=$(build)/loader.bin of=$(build)/ratsos.img bs=512 count=1 seek=1 conv=notrunc
$(build)/%.bin: $(boot)/%.asm
$(NASM) -f bin -o $(build)/$*.bin $(boot)/$*.asm
prepare: $(build)
@echo "prepare dir $(build)"
ifeq ($(build), $(wildcard $(build)))
@echo "build directory exist..."
else
mkdir -p $(build)
endif
clean:
@echo "clean dir $(build)"
rm -rf $(build)/*
platform:
@echo $(PLATFORM)
运行结果

读取磁盘:LBA方式的更多相关文章
- 读取磁盘:CHS方式
读取磁盘:CHS方式 BIOS读取磁盘 读取磁盘也是调用BIOS: 中断命令: INT 13H 读取扇区的入口参数为 AH = 02H 功能参数,读取扇区 AL = 扇区数 CH = 柱面 CL = ...
- 通过DeviceIoControl读磁盘的方式读取独占文件内容
前言 windows操作系统中常见的一个文件存储系统是NTFS.在这个文件系统中MFT是它的核心. 图一 MFT是一个数据结构,上图是它的结构,它主要用来存放每个文件和目录在磁 ...
- 【原创】Android 4.4前后版本读取图库图片方式的变化
Android 4.4前后版本读取图库图片方式的变化 本文讲述Android 4.4(KitKat)前后访问图库以及访问后通过图片路径读取图片的变化 Android 4.4(KitKat)以前 ...
- python读取配置文件的方式
python读取配置文件的方式 1.从config.ini中读取,后缀无所谓,文件名字也无所谓,不过config.ini是常用写法,所谓见名知意 config.ini内容: [global] ip = ...
- JavaWeb中servlet读取配置文件的方式
我们在JavaWeb中常常要涉及到一些文件的操作,比如读取配置文件,下载图片等等操作.那我们能不能采用我们以前在Java工程中读取文件的方式呢?废话不多说我们来看看下我们以前在Java工程中读取文件是 ...
- Windows Server 2003中报PerfDisk “无法从系统读取磁盘性能信息。
Windows Server 2003中报PerfDisk “无法从系统读取磁盘性能信息.”的问题解决 2015-01-22 09:49:02 标签:Windows Server2003 PerfDi ...
- Java读取配置文件的方式
Java读取配置文件的方式-笔记 1 取当前启动文件夹下的配置文件 一般来讲启动java程序的时候.在启动的文件夹下会有配置文件 classLoader.getResource(&qu ...
- linux初学者-磁盘分区方式篇
linux初学者-磁盘分区方式篇 一般的计算机都会采用mbr分区方式,这种分区方式只能够建立四个主分区,如果还需要或更多的分区,就需要将其中一个主分区建立成一个扩展分区,在里面建立逻辑分区,这些分区信 ...
- Java 将数据写入磁盘并读取磁盘上的文件
package test; import java.io.BufferedReader;import java.io.FileReader;import java.io.FileWriter;impo ...
随机推荐
- UVA 12345 Dynamic len(带修莫队)
Dynamic len [题目链接]Dynamic len [题目类型]带修莫队 &题解: 莫队可以单点更改,只要再多加一维,代表查询次数,排序的时候3个关键字. 之后循环离线的时候,先暴力时 ...
- python多线程学习二
本文希望达到的目标: 多线程同步原语:互斥锁 多线程队列queue 线程池threadpool 一.多线程同步原语:互斥锁 在多线程代码中,总有一些特定的函数或者代码块不应该被多个线程同时执行,通常包 ...
- HDU 1160
FatMouse believes that the fatter a mouse is, the faster it runs. To disprove this, you want to take ...
- 网页头部meta标签
<meta http-equiv="content-Type" content="text/html;charset=UTF-8"> //设置 ...
- 小程序canvas生成海报保存至手机相册
小程序canvas画图保存至手机相册 (1)可直接展示生成的海报 .因手机分辨率不同可能导致生成的海报会有细微差别,这里隐藏canvas海报,页面正常设置海报样式保存时保存隐藏的canvas海报 (2 ...
- 记录Js 文本框验证 与 IE兼容性
最近的日常就是将测试小姐姐提交的bug进行修改,想来这种事情还是比较好开展的,毕竟此项目已上线一年多,现在只是一些前端的问题需要改正.实际上手的时候并不是这样,原项目是在谷歌上运行,后来由于要新增一个 ...
- 浮点数(double、float)的格式化问题及处理
---恢复内容开始--- 平时常会面临浮点数的格式处理问题,下面就举例说一说常见的问题及处理: 1,科学计数法问题 一个浮点数123456789.10,在打印的时候变成了1.234567891E8,处 ...
- Ubuntu 16.04下vsftpd 安装配置实例
从https://www.linuxidc.com/Linux/2017-06/144807.htm转载 第一步:安装VSFTPD sudo apt-get install vsftpd 安装完成后启 ...
- [linux] grep 文本搜索工具
grep [option] pattern file Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来.grep全称是Global Regular ...
- Codeforces Round #495 (Div. 2) D. Sonya and Matrix
http://codeforces.com/contest/1004/problem/D 题意: 在n×m的方格中,选定一个点(x,y)作为中心点,该点的值为0,其余点的值为点到中心点的曼哈顿距离. ...