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方式的更多相关文章

  1. 读取磁盘:CHS方式

    读取磁盘:CHS方式 BIOS读取磁盘 读取磁盘也是调用BIOS: 中断命令: INT 13H 读取扇区的入口参数为 AH = 02H 功能参数,读取扇区 AL = 扇区数 CH = 柱面 CL = ...

  2. 通过DeviceIoControl读磁盘的方式读取独占文件内容

    前言 windows操作系统中常见的一个文件存储系统是NTFS.在这个文件系统中MFT是它的核心.             图一 MFT是一个数据结构,上图是它的结构,它主要用来存放每个文件和目录在磁 ...

  3. 【原创】Android 4.4前后版本读取图库图片方式的变化

    Android 4.4前后版本读取图库图片方式的变化   本文讲述Android 4.4(KitKat)前后访问图库以及访问后通过图片路径读取图片的变化   Android 4.4(KitKat)以前 ...

  4. python读取配置文件的方式

    python读取配置文件的方式 1.从config.ini中读取,后缀无所谓,文件名字也无所谓,不过config.ini是常用写法,所谓见名知意 config.ini内容: [global] ip = ...

  5. JavaWeb中servlet读取配置文件的方式

    我们在JavaWeb中常常要涉及到一些文件的操作,比如读取配置文件,下载图片等等操作.那我们能不能采用我们以前在Java工程中读取文件的方式呢?废话不多说我们来看看下我们以前在Java工程中读取文件是 ...

  6. Windows Server 2003中报PerfDisk “无法从系统读取磁盘性能信息。

    Windows Server 2003中报PerfDisk “无法从系统读取磁盘性能信息.”的问题解决 2015-01-22 09:49:02 标签:Windows Server2003 PerfDi ...

  7. Java读取配置文件的方式

    Java读取配置文件的方式-笔记 1       取当前启动文件夹下的配置文件   一般来讲启动java程序的时候.在启动的文件夹下会有配置文件 classLoader.getResource(&qu ...

  8. linux初学者-磁盘分区方式篇

    linux初学者-磁盘分区方式篇 一般的计算机都会采用mbr分区方式,这种分区方式只能够建立四个主分区,如果还需要或更多的分区,就需要将其中一个主分区建立成一个扩展分区,在里面建立逻辑分区,这些分区信 ...

  9. Java 将数据写入磁盘并读取磁盘上的文件

    package test; import java.io.BufferedReader;import java.io.FileReader;import java.io.FileWriter;impo ...

随机推荐

  1. python_json序列化和反序列化

    序列化 import json dic = {'} print(json.dumps(dic)) 反序列化;json.loads() dic = {'} print(json.dumps(dic)) ...

  2. linux下安装svn服务器

    http://www.cnblogs.com/zhoulf/archive/2013/02/02/2889949.html 安装说明系统环境:CentOS-6.3安装方式:yum install (源 ...

  3. Delphi数据库技术中Disablecontrols和Enablecontrols的功能

    一般来说,用来扫描整个数据库表并修改每个记录的某一个字段的程序如下所示: with Table Do begin DisableControls;{在修改记录的过程中,使其它部件无效} First; ...

  4. JavaScript 原型链学习(一)原型对象

    在JavaScript中创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有的实例共享的属性和方法.如果按照字面意思来理解 ...

  5. 6.MongoDB4.0在Windows环境的下载、安装、配置

    简单来说:MongoDB4.0在Windows下已经不需要再次配置db文件夹之类操作,安装完成直接进行连接测试即可,以下是具体过程(此前网上很多的教程都已经过时) 1.下载:https://www.m ...

  6. websocket 二合一

    server from flask import Flask, request, render_template from geventwebsocket.handler import WebSock ...

  7. 51Nod 1085 背包问题 (01背包)

    在N件物品取出若干件放在容量为W的背包里,每件物品的体积为W1,W2……Wn(Wi为整数),与之相对应的价值为P1,P2……Pn(Pi为整数).求背包能够容纳的最大价值. 收起   输入 第1行,2个 ...

  8. GoldenGate BR(bounded Recovery)简单说明

    背景 Oracle数据库的在线日志包含已提交的和未提交的事务,但OGG只会将已提交的事务写入到队列文件.因此,针对未提交的事务,特别是未提交的长事务,OGG会怎样处理呢? 有些长事务是在批处理作业中, ...

  9. Python select实现socket并发

    Python select  Python的select()方法直接调用操作系统的IO接口,它监控sockets,open files, and pipes(所有带fileno()方法的文件句柄)何时 ...

  10. vue elementui报错总结

    1.  错误: TypeError: _self.$scopedSlots.default is not a function 原因:这是因为在v-for/v-if切换标签时,原本这些标签每一个都是独 ...