读取磁盘:CHS方式
读取磁盘:CHS方式
BIOS读取磁盘
读取磁盘也是调用BIOS:
中断命令: INT 13H
读取扇区的入口参数为
AH = 02H 功能参数,读取扇区
AL = 扇区数
CH = 柱面
CL = 扇区
DH = 磁头
DL = 驱动器号,00H7FH:软盘驱动器号;80H0FFH:硬盘驱动器号
ES:BX = 缓冲区的地址
出口参数
CF = 0: 操作成功,AH = 00H,AL = 传输的扇区数
否则,AH = 状态代码
定义磁盘读取函数
1. 读取一个扇区
; ------------------------------------------------------------------------
; 读取一个扇区函数:ReadDisk0
; ------------------------------------------------------------------------
; 参数:ES:BX 缓冲区地址,CH柱面,DH磁头,CL扇区
; ------------------------------------------------------------------------
ReadDisk0:
MOV SI,0 ;初始化读取失败次数,用于循环计数
;为了防止读取错误,循环读取5次
;调用BIOS读取一个扇区
ReadFiveLoop:
MOV AH,0x02 ;BIOS中断参数:读扇区
MOV AL,1 ;BIOS中断参数:读取扇区数
MOV BX,0
MOV DL,0x00 ;BIOS中断参数:设置读取驱动器为软盘
INT 0x13 ;调用BIOS中断操作磁盘:读取扇区
JNC ReadEnd ;条件跳转,操作成功进位标志=0。则跳转执行ReadNextSector
inc si ;循环读取次数递增+1
CMP SI,5 ;判断是否已经读取超过5次
JAE LoadError ;上面cmp判断(>=)结果为true则跳转到DisplayError
MOV AH,0x00 ;BIOS中断参数:磁盘系统复位
MOV DL,0x00 ;BIOS中断参数:设置读取驱动器为软盘
INT 0x13 ;调用BIOS中断操作磁盘:磁盘系统复位
JMP ReadFiveLoop
;扇区读取完成
ReadEnd:
RET
2. 读取多个扇区
读取时要根据 扇区<磁头<柱面 的方式来读取。继续添加代码,读取18个扇区:(即完整的读取了一个柱面)。
代码如下:
3. 读取多个柱面
继续添加代码,读取10个柱面。
然后调用函数
;读取磁盘初始化
MOV AX,DISC_ADDR/0x10 ;设置磁盘读取的缓冲区基本地址为ES=0x820。[ES:BX]=ES*0x10+BX
MOV ES,AX ;BIOS中断参数:ES:BX=缓冲区的地址
MOV CH,0 ;设置柱面为0
MOV DH,0 ;设置磁头为0
MOV CL,2 ;设置扇区为2
ReadSectorLoop:
CALL ReadDisk0; ;读取一个扇区
转换LBA到CHS方式读取
; ==============================================
; 读取磁盘:Func_readCHS2LBA
; 参数:
; ebx 扇区逻辑号
; cx 读入的扇区数,8位
; es 读取到内存单元的地址
; ==============================================
.reset
MOV AH,0x00 ;BIOS中断参数:磁盘系统复位
MOV DL,0x00 ;BIOS中断参数:设置读取驱动器为软盘
INT 0x13 ;调用BIOS中断操作磁盘:磁盘系统复位
ret
.readdisk
;初始化读取失败次数,用于循环计数
push cx
MOV cx,5
;为了防止读取错误,循环读取5次
;调用BIOS读取一个扇区
ReadFiveLoop:
MOV AH,0x02 ;BIOS中断参数:读扇区
MOV AL,1 ;BIOS中断参数:读取扇区数
MOV BX,0
MOV DL,0x00 ;BIOS中断参数:设置读取驱动器为软盘
INT 0x13 ;调用BIOS中断操作磁盘:读取扇区
JNC .readok ;条件跳转,操作成功进位标志=0。则跳转执行ReadNextSector
inc si ;循环读取次数递增+1
CMP SI,5 ;判断是否已经读取超过5次
JAE .readfail ;上面cmp判断(>=)结果为true则跳转到DisplayError
call .reset
loop ReadFiveLoop
;准备下一个扇区
.readok:
MOV AX,ES
ADD AX,0x0020
MOV EX,AX ;内存单元基址后移0x20。[EX+0x20:]
ADD CL,1 ;读取扇区数递增+1
CMP CL,18 ;判断是否读取到18扇区
JBE readdisk ;上面cmp判断(<=)结果为true则跳转到DisplayError
.readxx
;读取另一面磁头。循环读取柱面
MOV CL,1 ;设置柱面为0
ADD DH,1 ;设置磁头递增+1:读取下一个磁头
CMP DH,2 ;判断磁头是否读取完毕
JB ReadSectorLoop ;上面cmp判断(<)结果为true则跳转到DisplayError
MOV DH,0 ;设置磁头为0
ADD CH,1 ;设置柱面递增+1;读取下一柱面
CMP CH,10 ;判断是否已经读取10个柱面
JB readdisk ;上面cmp判断(<)结果为true则跳转到DisplayError
完整代码
最后,完整的boot.asm文件代码如下:
;RATSBOOT
;TAB=4
;定义常量
DISC_ADDR EQU 0x8000 ;磁盘第一个扇区开始,加载到内存缓冲的地址
SECTOR_NUM EQU 18 ;读取扇区数
CYLINDER_NUM EQU 10 ;读取柱面数
ORG 0x7c00 ;指明程序的偏移的基地址
;以下这段是标准FAT32 格式软盘专用的代码
JMP Entry
DB 0x90 ;nop,0x02
DB "RATSBOOT" ;(8字节)启动区的名称可以是任意的字符串
DW 512 ;每个扇区(sector)的大小(必须为512 字节)
DB 8 ;簇(cluster )的大小(每个簇为8个扇区)
DW 584 ;保留扇区数,包括启动扇区
DB 2 ;FAT的个数(必须为2)
DW 0 ;最大根目录条目个数
DW 0 ;总扇区数(如果是0,就使用偏移0x20处的4字节值)
DB 0x00f8 ;磁盘介质描述
DW 0 ;(FAT16)每个文件分配表的扇区
DW 63 ;每个磁道扇区数
dw 255 ;磁头数
dd 63 ;隐藏扇区
dd 3902913 ;磁盘大小,总共扇区数(如果超过65535,参见偏移0x13)
dd 3804 ;每个文件分配表的扇区,3804个扇区
dw 0 ;Flagss
dw 0 ;版本号
dd 2 ;根目录启始簇
dw 1 ;FSInfo扇区
dw 6 ;启动扇区备份
times 12 db 0 ;保留未使用
DW 0 ;操作系统自引导代码
db 0x80 ;BIOS设备代号
db 0 ;未使用
db 0x29 ;标记
DD 0xffffffff ;序列号
DB "HELLO-OS " ;(11字节)磁盘名称,卷标。字符串长度固定
DB "FAT32 " ;(8字节)FAT文件系统类型。 0x52
times 12 db 0
;程序核心内容
Entry:
MOV AX,0 ;初始化寄存器
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX
MOV DI,StartMessage ;将Message1段的地址放入SI
CALL DisplayStr ;调用函数
MOV DI,BootMessage ;将Message1段的地址放入SI
ADD DH,1
CALL DisplayStr ;调用函数
;读取磁盘初始化
MOV AX,DISC_ADDR/0x10 ;设置磁盘读取的缓冲区基本地址为ES=0x820。[ES:BX]=ES*0x10+BX
MOV ES,AX ;BIOS中断参数:ES:BX=缓冲区的地址
MOV CH,0 ;设置柱面为0
MOV DH,0 ;设置磁头为0
MOV CL,1 ;设置扇区为2
ReadSectorLoop:
CALL ReadDisk0; ;读取一个扇区
;准备下一个扇区
ReadNextSector:
MOV AX,ES
ADD AX,0x0020
MOV ES,AX ;内存单元基址后移0x20(512字节)。[ES+0x20:]
ADD CL,1 ;读取扇区数递增+1
CMP CL,SECTOR_NUM ;判断是否读取到18扇区
JBE ReadSectorLoop ;上面cmp判断(<=)结果为true则跳转到DisplayError
;读取另一面磁头。循环读取柱面
MOV CL,1 ;设置柱面为0
ADD DH,1 ;设置磁头递增+1:读取下一个磁头
CMP DH,2 ;判断磁头是否读取完毕
JB ReadSectorLoop ;上面cmp判断(<)结果为true则跳转到DisplayError
MOV DH,0 ;设置磁头为0
ADD CH,1 ;设置柱面递增+1;读取下一柱面
CMP CH,CYLINDER_NUM ;判断是否已经读取10个柱面
JB ReadSectorLoop ;上面cmp判断(<)结果为true则跳转到DisplayError
;LoadSuccess:
MOV DI,Succmsg
MOV DH,3
CALL DisplayStr ;此处必须注释掉,不能调用INT。原因不明。
;加载执行boot文件:
;MOV [0x0ff0],CH ;将总共读取的柱面数存储在内存单元中
;JMP 0xc200 ;跳转执行在内存单元0xc200的代码
GoLoader:
MOV [0x0ff0],CH ;将总共读取的柱面数存储在内存单元中
JMP 0xc200 ;跳转执行在内存单元0xc200的代码:DISC_ADDR-0x200+0x4200
;(启动扇区开始地址0x8000+软盘代码:boot文件开始0x4200)
LoadError:
MOV DI,Errormsg
MOV DH,3
CALL DisplayStr ;如果加载失败显示加载错误
;程序挂起
Fin:
HLT ;让CPU挂起,等待指令。
JMP Fin
; ------------------------------------------------------------------------
; 读取一个扇区函数:ReadDisk0
; ------------------------------------------------------------------------
; 参数:ES:BS 缓冲区地址,CH柱面,DH磁头,CL扇区,AL扇区数=1,DL驱动器=0x
; ------------------------------------------------------------------------
ReadDisk0:
MOV SI,0 ;初始化读取失败次数,用于循环计数
;为了防止读取错误,循环读取5次
;调用BIOS读取一个扇区
ReadFiveLoop:
MOV AH,0x02 ;BIOS中断参数:读扇区
MOV AL,1 ;BIOS中断参数:读取扇区数
MOV BX,0
MOV DL,0x00 ;BIOS中断参数:设置读取驱动器为软盘
INT 0x13 ;调用BIOS中断操作磁盘:读取扇区
JNC ReadEnd ;条件跳转,操作成功进位标志=0。则跳转执行ReadNextSector
ADD SI,1 ;循环读取次数递增+1
CMP SI,5 ;判断是否已经读取超过5次
JAE LoadError ;上面cmp判断(>=)结果为true则跳转到DisplayError
MOV AH,0x00 ;BIOS中断参数:磁盘系统复位
MOV DL,0x00 ;BIOS中断参数:设置读取驱动器为软盘
INT 0x13 ;调用BIOS中断操作磁盘:磁盘系统复位
JMP ReadFiveLoop
;扇区读取完成
ReadEnd:
RET
; ------------------------------------------------------------------------
; 显示字符串函数:DisplayStr
; ------------------------------------------------------------------------
; 参数:SI:字符串开始地址, DH为第N行
; ------------------------------------------------------------------------
DisplayStr:
MOV CX,0 ;BIOS中断参数:显示字符串长度
MOV BX,DI
.1:;获取字符串长度
MOV AL,[BX] ;读取1个字节。这里必须为AL
ADD BX,1 ;读取下个字节
CMP AL,0 ;是否以0结束
JE .2
ADD CX,1 ;计数器
JMP .1
.2:;显示字符串
MOV BX,DI
MOV BP,BX
MOV AX,DS
MOV ES,AX ;BIOS中断参数:计算[ES:BP]为显示字符串开始地址
MOV AH,0x13 ;BIOS中断参数:显示文字串
MOV AL,0x01 ;BIOS中断参数:文本输出方式(40×25 16色 文本)
MOV BH,0x0 ;BIOS中断参数:指定分页为0
MOV BL,0x0c ;BIOS中断参数:指定白色字体07
MOV DL,0 ;列号为0
INT 0x10 ;调用BIOS中断操作显卡。输出字符
RET
;数据初始化
StartMessage: DB "hello,rats os start",0
BootMessage: DB "booting............",0
Errormsg: DB "load error ",0
Succmsg: DB "load success",0
FillSector:
RESB 510-($-$$) ;处理当前行$至结束(1FE)的填充
DB 0x55, 0xaa
运行结果如下:

上面代码的作用
首先boot.asm会被加载到内存并且执行.后面开始读取磁盘的10个柱面(10*18个扇区).
读取的扇区数据复制到 内存 0x8000 开始的位置.
然后打印输出"hello,rats os start"
读取磁盘:CHS方式的更多相关文章
- 读取磁盘:LBA方式
LBA简介 磁盘读取发展 IO操作读取硬盘的三种方式: chs方式 :小于8G (8064MB) LBA28方式:小于137GB LBA48方式:小于144,000,000 GB LBA方式访问使用了 ...
- 通过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 ...
随机推荐
- [ Python ] OpenGL
pyOpenGL Installation Package Version------------------- -------numpy 1.14.2 PyOpenGL 3.1.0 PyOpenGL ...
- Dom4j基础
dom4j是一个非常非常优秀的Java XML API,用来读写XML文件,具有性能优异.功能强大和易于使用的特点,同时它也是一个开放源代码的软件,可以在SourceForge上找到它.对主流的Jav ...
- Solution about MB STAR C4, MB STAR C5 Update and can not test vehicles problems
Solution about MB Star C4, MB Star C5 Update and can not test vehicles problems 1. Make sure your co ...
- L2-025. 分而治之
分而治之,各个击破是兵家常用的策略之一.在战争中,我们希望首先攻下敌方的部分城市,使其剩余的城市变成孤立无援,然后再分头各个击破.为此参谋部提供了若干打击方案.本题就请你编写程序,判断每个方案的可行性 ...
- Docker Kubernetes 创建管理 Pod
Docker Kubernetes 容器扩容与缩容 环境: 系统:Centos 7.4 x64 Docker版本:18.09.0 Kubernetes版本:v1.8 管理节点:192.168.1.79 ...
- day04流程控制,if分支结构,while,for循环
复习 ''' 1.变量名命名规范 -- 1.只能由数字.字母 及 _ 组成 -- 2.不能以数字开头 -- 3.不能与系统关键字重名 -- 4._开头有特殊含义 -- 5.__开头__结尾的变量,魔法 ...
- 年度游戏圈2018白皮书解析手游折扣app哪个好及靠谱程度分析
2018年,随着全国暂停游戏版本的审核和发布<综合防控儿童青少年近视实施方案>(控制新的在线游戏数量),游戏行业受到的影响不小. 在游戏产业中,游戏行业2018年的收入同比增长5.2%,远 ...
- 王之泰201771010131《面向对象程序设计(java)》第九周学习总结
第一部分:理论知识学习部分 第7章异常.日志.断言和调试 概念:异常.异常类型.异常声明.异常抛出. 异常捕获1.异常处理技术2.断言的概念及使用3.基本的调试技巧 1)异常的概念 a.Java的异常 ...
- 输出JSON
<?php header("Content-type: text/html; charset=utf-8"); $host = '数据库IP'; $dbname = '数据库 ...
- linux基础之正则表达式
一.基本正则表达式 字符匹配 . : 匹配任意单个字符 [] : 匹配中括号中的任意单个字符 [^] : 匹配指定范围外的任意单个字符 空白字符:[:space:].数字:[:digit:].小写字母 ...