磁盘lba是什么,硬盘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寄存器0x1F3lba地址的低8位LBA mid寄存器0x1F4lba地址的中8位LBA high寄存器0x1F5lba地址的高8位device寄存器0x1F6lba地址的前4位(占用device寄存器的低4位)
主盘值为0(占用device寄存器的第5位)
第6位值为1
LBA模式为1,CHS模式为0(占用device寄存器的第7位)
第8位值为1command寄存器0x1F7读取,写入的命令,返回磁盘状态
1 读取扇区:0x20 写入扇区:0x30
磁盘识别:0xEC

IDE通道1,读写0x1f0-0x1f7号端口

IDE通道2,读写0x170-0x17f号端口

CHS方式:

写0x1f1: 0

写0x1f2: 要读的扇区数

写0x1f3: 扇区号W

写0x1f4: 柱面的低8位

写0x1f5: 柱面的高8位

写0x1f6: 7~5位,101,第4位0表示主盘,1表示从盘,3~0位,磁头号

写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: 7~5位,111,第4位0表示主盘,1表示从盘,3~0位,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: 7~5位,010,第4位0表示主盘,1表示从盘,3~0位,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 retFillSector: 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命令

# toolsPLATFORM=LinuxNASM=nasmQEMU=qemu-system-x86_64QEMU-IMG=qemu-imgBOCHS=bochsBX-IMG=bximage# argsboot=bootbuild=buildtarget: prepare img $BOCHS) -f bochsrc.meimg: $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) endifclean: @echo “clean dir $build)” rm -rf $build)/*platform: @echo $PLATFORM)

运行结果

转载于:https://www.cnblogs.com/mlzrq/p/10223060.html

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注