自己动手从零写桌面操作系统GrapeOS系列教程——21.汇编语言写硬盘实战
学习操作系统原理最好的方法是自己写一个简单的操作系统。
在上一讲中我们学习了用汇编语言读硬盘,本讲我们来学习用汇编语言写硬盘。同样也是设计一个简单的实验,实验内容为:
在内存中准备一段有特征的512字节数据,地址为0x7e00~0x7fff,其特征是前3个字节依次为4、5、6,最后3个字节依次为6、5、4。然后将该段内存数据写入到硬盘的第2个扇区,并查看虚拟硬盘第2个扇区的数据是否与内存中0x7e00~0x7fff的数据一致,如果一致则说明写硬盘成功。
本讲代码文件只有一个boot2.asm。
boot2.asm代码如下:
;定义常量
DISK_BUFFER equ 0x7e00 ;临时存放数据用的缓存区,放到boot程序之后。0x7e00~0x7fff。
org 0x7c00
;初始化段寄存器
mov ax,cs
mov ds,ax ;ds指向与cs相同的段
mov bx,DISK_BUFFER
;向缓存区前3个字节依次写入4、5、6。
mov byte [bx+0],4
mov byte [bx+1],5
mov byte [bx+2],6
;向缓存区最后3个字节依次写入6、5、4。
mov byte [bx+509],6
mov byte [bx+510],5
mov byte [bx+511],4
mov si,DISK_BUFFER
mov edi,1 ;写入硬盘的第2个扇区
call func_write_one_sector
stop:
hlt
jmp stop
;将内存中的512个字节写入到硬盘的一个指定扇区中(主硬盘控制器主盘)
;输入参数:ds:si,edi。
;ds:si 数据源内存地址
;edi LBA扇区号
;输出参数:无。
func_write_one_sector:
;第1步:检查硬盘控制器状态
mov dx,0x1f7
.not_ready1:
nop ;nop相当于稍息 hlt相当于睡觉
in al,dx ;读0x1f7端口
and al,0xc0 ;第7位为1表示硬盘忙,第6位为1表示硬盘控制器已准备好,正在等待指令。
cmp al,0x40 ;当第7位为0,且第6位为1,则进入下一个步。
jne .not_ready1 ;若未准备好,则继续判断。
;第2步:设置要写入的扇区数
mov dx,0x1f2
mov al,1
out dx,al ;写入1个扇区
;第3步:将LBA地址存入0x1f3~0x1f6
mov eax,edi
;LBA地址7~0位写入端口0x1f3
mov dx,0x1f3
out dx,al
;LBA地址15~8位写入端口写入0x1f4
shr eax,8
mov dx,0x1f4
out dx,al
;LBA地址23~16位写入端口0x1f5
shr eax,8
mov dx,0x1f5
out dx,al
;第4步:设置device端口
shr eax,8
and al,0x0f ;LBA第24~27位
or al,0xe0 ;设置7~4位为1110,表示LBA模式,主盘
mov dx,0x1f6
out dx,al
;第5步:向0x1f7端口写入写命令0x30
mov dx,0x1f7
mov al,0x30
out dx,al
;第6步:检测硬盘状态
.not_ready2:
nop ;nop相当于稍息 hlt相当于睡觉
in al,dx ;读0x1f7端口
and al,0x88 ;第7位为1表示硬盘忙,第3位为1表示硬盘控制器已准备好数据传输。
cmp al,0x08 ;当第7位为0,且第3位为1,进入下一步。
jne .not_ready2 ;若未准备好,则继续判断。
;第7步:向0x1f0端口写数据
mov cx,256 ;每次写入2字节,一个扇区需要写256次。
mov dx,0x1f0
.go_on_write:
mov ax,[si]
out dx,ax
add si,2
loop .go_on_write
ret
times 510-($-$$) db 0
db 0x55,0xaa
之前我们介绍过读硬盘操作和写硬盘操作都是7个步骤,其中只有第5步和第7步不同,其它步骤完全相同,大家可以和上一讲中的代码对比看一下。
下面我们将boot2.asm编译并写入到虚拟硬盘的第一个扇区:
nasm boot2.asm -o boot2.bin
dd conv=notrunc if=boot2.bin of=/media/VMShare/GrapeOS.img

此时用hexdum命令查看一下虚拟硬盘第二个扇区当前的数据,截图如下:

从上面的截图可以看到,此时虚拟硬盘第二个扇区前3个字节依次为1、2、3,最后3个字节依次为3、2、1。
下面我们以调试模式运行QEMU:
qemu-system-i386 d:\GrapeOS\VMShare\GrapeOS.img -S -s


通过GDB连接到QEMU,直接输入GDB命令c,让程序运行几秒钟,然后Ctrl+C,让程序暂停。此时写硬盘程序应该已经运行完了。此时查看一下内存0x7e00~0x7fff的数据:
(gdb) x /512xb 0x7e00


从上面截图可以看到,在内存0x7e00~0x7fff的数据中,前3个字节依次为4、5、6,最后3个字节依次为6、5、4,其余全是0。如果程序运行正确的话,此时硬盘第二扇区中的数据与此相同。
下面我们退出GDB,并关闭QEMU。然后用hexdum命令再查看一下虚拟硬盘第二个扇区的数据,截图如下:

从上面截图中可以看到,硬盘第二扇区的数据与内存中0x7e00~0x7fff的数据一致,说明写入成功,实验完毕。
本讲视频版地址:https://www.bilibili.com/video/BV1Hk4y187Bw/
配套的代码与资料在:https://gitee.com/jackchengyujia/grapeos-course
GrapeOS操作系统交流QQ群:643474045
自己动手从零写桌面操作系统GrapeOS系列教程——21.汇编语言写硬盘实战的更多相关文章
- 别人写的一个Bootstrap系列教程
http://www.cnblogs.com/lansy/category/659061.html
- 一个人写的操作系统 - Sparrow OS
一个人写的操作系统 - Sparrow OS 自己写一个操作系统,这是在过去的几年里我一直为之努力的目标,现在终于完成了. 缘起 自己动手写操作系统的动机最初来自于学习Linux遇到的困难. 我是一个 ...
- 自制 os 极简教程1:写一个操作系统有多难
为什么叫极简教程呢?听我慢慢说 不知道正在阅读本文的你,是否是因为想自己动手写一个操作系统.我觉得可能每个程序员都有个操作系统梦,或许是想亲自动手写出来一个,或许是想彻底吃透操作系统的知识.不论是为了 ...
- 【操作系统】关于Linux桌面操作系统
以前是Win+Ubuntu+黑苹果,周末想体验一下deepin,于是简单安装了一下,安装过程很简单,这里不再描述.安装之后,第一次打开系统,确实很惊艳,赏心悦目的操作系统. 之前用Ubuntu时候,C ...
- 盘点|2021年最受欢迎Linux桌面操作系统前十名
镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 阿里云开源镜像站利用云服务上的优势,提供快速.稳定的镜像分发服务.和免费的CDN加速服务.更新频率高,基本上一天一更新,对于Centos/Ubun ...
- 《一步一步写嵌入式操作系统》读书笔记1—Skyeye介绍、安装和HelloWorld
2013-11-14 最近在看<一步一步写嵌入式操作系统>,感觉此书甚好,许多地方讲得很清楚.可操作性强,计划边读边实践边写笔记,希望能够逐步熟悉嵌入式操作系统底层的东西,最终剪裁出一套实 ...
- Zedboard学习(一):移植Ubuntu桌面操作系统 标签: ubuntu移植zedboardFPGA 2017-07-04 21:53 26人阅读
环境准备: 首先,需要的肯定是Ubuntu操作系统.可以在自己的电脑上安装物理机,也可以是虚拟机下运行的.我的是在Vmware下运行的Ubuntu14.04 32位操作系统. 由于zedboard上的 ...
- 我是如何学习写一个操作系统(二):操作系统的启动之Bootloader
前言 今天本来的任务看书和把之前写的FragileOS整理一下,但是到现在还在摸鱼,书也只看一点.后来整理了一下写这个系列的思路,原本的目的是对操作系统原理性的学习和对之前写的一个玩具型操作系统的回顾 ...
- 自己动手写Vector【Cherno C++教程】
动手写一个Vector 本文是对<最好的C++教程>的动手写数据结构部分的一个整理,主要包含91p动手写Array数组和92p动手写Vector数组的内容. 自己动手来写这些数据结构是学习 ...
- 红旗 Linux 桌面操作系统11来了:支持国产自主CPU,全新UI风格设计,兼容面广...
链接:https://reurl.cc/g8ke9X 红旗Linux桌面操作系统11将于1月10日开放预览版的下载,新版本具有良好的硬件兼容,支持多款国产自主CPU品牌,同时还具有丰富的外设支持及海量 ...
随机推荐
- IIS10.0 Web平台安装程序无法安装URL重写工具
Windows10系统的IIS10.0需要安装URL rewrite重写模块2.0,提示"很遗憾,无法安装下列产品",解决方法: win键+R键,运行regedit,打开注册表编辑 ...
- shell_Day01
1.判断/etc/inittab文件是否大于100行,如果大于,则显示"/etc/inittab is a big file."否者显示"/etc/inittab is ...
- C# net core 从文件流中获取文件头、匹配文件类型
常用文件的文件头如下: (以前六位为准) JPEG (jpg),文件头:FFD8FF PNG (png),文件头:89504E47 GIF (gif),文件头:47494638 TIFF (tif), ...
- 网络同步时钟单路耐压测试突破17V
自动同步标准化考场时钟系统------专业LED时钟厂家![点击进入] 一.网络同步时钟耐压测试作用概述: 同步时钟耐压试验是鉴定时钟绝缘强度和稳定性最直接的方法,它对于判断NTP同步时钟设备能否投入 ...
- PPT之图表
1.从数据到信息 同样的数据,通过不同的图样式来呈现不同的突出重点.使用饼状图突出元素占比,使用排序的柱状图突出最大或者最小的元素,使用虚化与实体突出表达重点. 同样的数据,通过不同的关注点突出重点. ...
- GIS介绍(详细)一、什么是GIS?
其他GIS空间分析文章 博主的参考书籍是科学出版社的地理信息系统原理(华一新.赵军喜等) 一.什么是GIS? 要说明什么是GIS,我们就得学习其基本术语,从而引出GIS的定义: 1.信息 狭义的信息论 ...
- 获取n位数m进制的随机数 js
js 获取n位数m进制的随机数 n 的取值范围为 0 < n > 1.7976931348623157e+308 (Number.MAX_VALUE) m的取值范围为 2 <= m ...
- SQL语句底层执行顺序
1. SELECT 语句的完整结构 SQL92语法: SELECT ...,....,(存在聚合函数) FROM ...,...,... WHERE 多表的连接条件 AND 不包含聚合函数的过滤条件 ...
- pintia 3-7-5 逆波兰表达式求值 (20 分)
3-7-5 逆波兰表达式求值 (20 分) 逆波兰表示法是一种将运算符(operator)写在操作数(operand)后面 的描述程序(算式)的方法.举个例子,我们平常用中缀表示法描述的算式(1 + ...
- linux 获取文件名
https://blog.csdn.net/liuyuedechuchu/article/details/123778605