读取磁盘: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 ...
随机推荐
- pyCharm添加自己的快捷代码
1.首先打开pyCharm 2.打开Settings 3.输入live点击打开 Templates 4.选中python点击"+"号 5.选择Live Template 6.以打开 ...
- C#中Abstract和Virtual(转载)
在C#的学习中,容易混淆virtual方法和abstract方法的使用,现在来讨论一下二者的区别.二者都牵涉到在派生类中与override的配合使用. 一.Virtual方法(虚方法) virtual ...
- linux下git服务器安装
git服务器配置http://www.cnblogs.com/dee0912/p/5815267.html git教程https://www.liaoxuefeng.com/wiki/00137395 ...
- acm 2015北京网络赛 F Couple Trees 主席树+树链剖分
提交 题意:给了两棵树,他们的跟都是1,然后询问,u,v 表 示在第一棵树上在u点往根节点走 , 第二棵树在v点往根节点走,然后求他们能到达的最早的那个共同的点 解: 我们将第一棵树进行书链剖,然后第 ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- jQuery 新建函数
jQuery 新建函数 格式一: // 格式一:新建添加函数方法并使用 $.extend({ 'xsk':function () { return 'xsk'; } }); // 调用 $.xsk() ...
- PHP实现简单发红包(随机分配,平均分配)
最近碰到一些情况,把思路重新整理了一下,敲出代码.记下来,以后可以借鉴,进一步优化等. 大致的思路:红包主要分两种,一种是平均分配,一种是随机分配. 1.平均分配 平均分配相对好理解,只要把钱平均分给 ...
- Codeforces 939C - Convenient For Everybody
2018-03-03 http://codeforces.com/problemset/problem/939/C C. Convenient For Everybody time limit per ...
- Canonical Coin Systems【完全背包】
问题 C: Canonical Coin Systems 时间限制: 1 Sec 内存限制: 128 MB 提交: 200 解决: 31 [提交] [状态] [命题人:admin] 题目描述 A ...
- MyBatis进阶(二)
MyBatis之动态SQL 动态SQL之foreach 有时SQL语句where条件是在一个集合或者数组里,需要使用in关键字,这时可以使用foreach动态SQL语句,例如: select * fr ...