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处执行指令。

  1. ;Rats OS
  2. ;Tab=4
  3. [bits 16]
  4. org 0x7c00 ;指明程序的偏移的基地址
  5. ;----------- loader const ------------------
  6. LOADER_SECTOR_LBA equ 0x1 ;第2个逻辑扇区开始
  7. LOADER_SECTOR_COUNT equ 9 ;读取9个扇区
  8. LOADER_BASE_ADDR equ 0x9000 ;内存地址0x9000
  9. ;-------------------------------------------
  10. ;引导扇区代码
  11. jmp Entry
  12. db 0x90
  13. db "RATSBOOT" ;启动区的名称可以是任意的字符串(8字节)
  14. ;程序核心内容
  15. Entry:
  16. ;------------------
  17. ;初始化寄存器
  18. mov ax,0
  19. mov ss,ax
  20. mov ds,ax
  21. mov es,ax
  22. mov ss,ax
  23. mov fs,ax
  24. mov gs,ax
  25. mov sp,0x7c00
  26. ;------------------
  27. ;清屏
  28. mov ah,0x06 ;清除屏幕
  29. mov al,0
  30. mov cx,0
  31. mov dx,0xffff
  32. mov bh,0x17 ;属性为蓝底白字
  33. int 0x10
  34. mov ah,0x02 ;光标位置初始化
  35. mov dx,0
  36. mov bh,0
  37. mov dh,0x0
  38. mov dl,0x0
  39. int 0x10
  40. ;------------------
  41. ;读取硬盘1-10扇区
  42. mov ebx,LOADER_SECTOR_LBA ;LBA扇区号
  43. mov cx,LOADER_SECTOR_COUNT ;读取扇区数
  44. mov di,LOADER_BASE_ADDR ;写入内存地址
  45. call Func_ReadLBA16
  46. jmp LOADER_BASE_ADDR
  47. ; ------------------------------------------------------------------------
  48. ; 读取磁盘:Func_ReadLBA16
  49. ; 参数:
  50. ; ebx 扇区逻辑号
  51. ; cx 读入的扇区数,8
  52. ; di 读取后的写入内存地址
  53. ; ------------------------------------------------------------------------
  54. Func_ReadLBA16:
  55. ;设置读取的扇区数
  56. mov al,cl
  57. mov dx,0x1F2
  58. out dx,al
  59. ;设置lba地址
  60. ;设置低8
  61. mov al,bl
  62. mov dx,0x1F3
  63. out dx,al
  64. ;设置中8
  65. shr ebx,8
  66. mov al,bl
  67. mov dx,0x1F4
  68. out dx,al
  69. ;设置高8
  70. shr ebx,8
  71. mov al,bl
  72. mov dx,0x1F5
  73. out dx,al
  74. ;设置高4位和device
  75. shr ebx,8
  76. and bl,0x0F
  77. or bl,0xE0
  78. mov al,bl
  79. mov dx,0x1F6
  80. out dx,al
  81. ;设置commond
  82. mov al,0x20
  83. mov dx,0x1F7
  84. out dx,al
  85. .check_status:;检查磁盘状态
  86. nop
  87. in al,dx
  88. and al,0x88 ;第4位为1表示硬盘准备好数据传输,第7位为1表示硬盘忙
  89. cmp al,0x08
  90. jnz .check_status ;磁盘数据没准备好,继续循环检查
  91. ;设置循环次数到cx
  92. mov ax,cx ;乘法ax存放目标操作数
  93. mov dx,256
  94. mul dx
  95. mov cx,ax ;循环次数 = 扇区数 x 512 / 2
  96. mov bx,di
  97. mov dx,0x1F0
  98. .read_data:
  99. in ax,dx ;读取数据
  100. mov [bx],ax ;复制数据到内存
  101. add bx,2 ;读取完成,内存地址后移2个字节
  102. loop .read_data
  103. ret
  104. FillSector:
  105. resb 510-($-$$) ;处理当前行$至结束(1FE)的填充
  106. db 0x55, 0xaa

loader.asm

被引导扇区加载到0x90000位置,执行输出hello in loader文字

  1. ;Rats OS
  2. ;Tab=4
  3. [bits 16]
  4. section loader vstart=LOADER_BASE_ADDR ;指明程序的偏移的基地址
  5. ;----------- loader const ------------------
  6. LOADER_BASE_ADDR equ 0x9000 ;内存地址0x9000
  7. ;---------------------------------------
  8. jmp Entry
  9. ;程序核心内容
  10. Entry:
  11. ;---------------------------
  12. ;输出字符串
  13. mov si,HelloMsg ;将HelloMsg的地址放入si
  14. mov dh,0 ;设置显示行
  15. mov dl,0 ;设置显示列
  16. call Func_Sprint ;调用函数
  17. jmp $ ;让CPU挂起,等待指令
  18. ; ------------------------------------------------------------------------
  19. ; 显示字符串函数:Func_Sprint
  20. ; 参数:
  21. ; si = 字符串开始地址,
  22. ; dh = N行,0开始
  23. ; dl = N列,0开始
  24. ; ------------------------------------------------------------------------
  25. Func_Sprint:
  26. mov cx,0 ;BIOS中断参数:显示字符串长度
  27. mov bx,si
  28. .len:;获取字符串长度
  29. mov al,[bx] ;读取1个字节到al
  30. inc bx ;读取下个字节
  31. cmp al,0 ;是否以0结束
  32. je .sprint
  33. inc cx ;计数器
  34. jmp .len
  35. .sprint:;显示字符串
  36. mov bx,si
  37. mov bp,bx
  38. mov bx,ds
  39. mov es,bx ;BIOS中断参数:计算[ES:BP]为显示字符串开始地址
  40. mov ah,0x13 ;BIOS中断参数:中断模式
  41. mov al,0x01 ;BIOS中断参数:输出方式
  42. mov bh,0x0 ;BIOS中断参数:指定分页为0
  43. mov bl,0x1F ;BIOS中断参数:显示属性,指定白色文字
  44. int 0x10 ;调用BIOS中断操作显卡。输出字符串
  45. ret
  46. ; ------------------------------------------------------------------------
  47. ;准备显示字符串
  48. HelloMsg: db "hello in loader!",0
  49. times 512-($-$$) db 0 ; 处理当前行$至结束(1FE)的填充

运行

创建Makefile文件,并执行make命令

  1. # tools
  2. PLATFORM=Linux
  3. NASM=nasm
  4. QEMU=qemu-system-x86_64
  5. QEMU-IMG=qemu-img
  6. BOCHS=bochs
  7. BX-IMG=bximage
  8. # args
  9. boot=boot
  10. build=build
  11. target: prepare img
  12. $(BOCHS) -f bochsrc.me
  13. img: $(build)/ratsos.img
  14. @echo "build img completed"
  15. $(build)/ratsos.img:$(build)/boot.bin $(build)/loader.bin
  16. $(BX-IMG) -hd -mode=flat -size=32 -q $(build)/ratsos.img
  17. sleep 1
  18. dd if=$(build)/boot.bin of=$(build)/ratsos.img bs=512 count=1 conv=notrunc
  19. dd if=$(build)/loader.bin of=$(build)/ratsos.img bs=512 count=1 seek=1 conv=notrunc
  20. $(build)/%.bin: $(boot)/%.asm
  21. $(NASM) -f bin -o $(build)/$*.bin $(boot)/$*.asm
  22. prepare: $(build)
  23. @echo "prepare dir $(build)"
  24. ifeq ($(build), $(wildcard $(build)))
  25. @echo "build directory exist..."
  26. else
  27. mkdir -p $(build)
  28. endif
  29. clean:
  30. @echo "clean dir $(build)"
  31. rm -rf $(build)/*
  32. platform:
  33. @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. PSPnet模型结构的实现代码

    1 import torch import torch.nn.functional as F from torch import nn from torchvision import models f ...

  2. JS函数预解析(小记)

    一,预解析:寻找var  function  形参     a=undefined    fn = function fn(){ alert(); } 二,逐行解读代码:    1.表达式    2. ...

  3. Vue将px转化为rem适配移动端

    Vue将px转化为rem适配移动端 1.下载lib-flexible我使用的是vue-cli+webpack,所以是通过npm来安装的npm i lib-flexible --save 2.引入lib ...

  4. MySQL数据的导出和导入

    MySQL环境变量设置,将%MySQL_HOME%下的MySQL Server 5.1/bin放到Path下. MySQL的mysqldump工具,基本用法是:   shell> mysqldu ...

  5. 校验input 修改当前值的校验获取值方式

    <input style="height: 18px; width: 90px;" name="nowQty" value="${ad.nowQ ...

  6. 20190408Linux权限管理week1_day5

    权限概述 Linux系统一般将文件可存/取访问的身份分为3个类别:owner(拥有者).group(和所有者同组的用户).others(其他人,除了所有者,除了同组的用户以及除了超级管理员),且3种身 ...

  7. 【Alpha】Scrum Meeting 1

    前言 第1次会议在3月17日由PM在教一317召开. 主要确定了选题,并对目标进行了初步的确定.时长90min. 任务分配 姓名 当前阶段任务 下阶段任务 吴昊 确定项目方向,本地部署代码,完成团队介 ...

  8. [pytorch修改]npyio.py 实现在标签中使用两种delimiter分割文件的行

    from __future__ import division, absolute_import, print_function import io import sys import os impo ...

  9. vector、map 判断某元素是否存在、查找指定元素

    一.vector 1.判断某元素是否存在 vector<string> vStr; int nRet = std::count(vStr.begin(), vStr.end(), &quo ...

  10. windows升级node

    之前用的node版本太低,不兼容webpack4.x,需要升级,网上搜索了许多方法,发现在windows下行不通 找到的教程都说全局安装node下的一个名为n的模块,这个模块是node专门用于版本管理 ...