自己动手从零写桌面操作系统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品牌,同时还具有丰富的外设支持及海量 ...
随机推荐
- 训练题——DS18B20部分
Author:Cherry_Ywj 0. 前言 本文档以 DS18B20 为例,主要介绍如何针对一种传感器编写相应的驱动库,驱动是单片机开发中难度较大的一环.从看别人代码并对照 datasheet 开 ...
- js判断变量数据类型typeof、instanceof、Object.prototype.toString.call()、 constructor
JavaScript有4种方法判断变量的类型,分别是typeof.instanceof.Object.prototype.toString.call()(对象原型链判断方法). constructor ...
- 2022-07-10 第一小组 张明旭 前端CSS学习记录
今天是正式学习的第二天,昨天那个作业项目真的难,自己做一会就得问这问那,还有大神带一带(?_?)... 今天学习的内容是前端中的CSS,男上加男..... 知识点: Css层叠式表(网页美化) 1.定 ...
- 1903021126 申文骏 Java 第六周作业 类与对象
项目 内容 课程班级博客链接 19级信计班(本) 作业要求链接 第六周作业 博客名称 1903021126 申文骏 Java 第六周作业 类与对象 要求 每道题要有题目,代码(使用插入代码,不会 ...
- 10 soundJs 初体验
最近想做一个h5的小游戏所以用上了soundjs. 还在开发中 http://www.hetenglife.com/mouse/game.html 刚刚把控制做完. 首先是要导入这个文件 <s ...
- Java mysql批量关联插入数据
mysql 关联批量插入数据 INSERT INTO 表1 ( id, name, addTime ) SELECT UUID( ) AS id, v_Name, now( ) FROM 表2;
- C语言初级阶段7——指针1
C语言初级阶段7--指针1 地址与指针 1.地址:数据在内存中的存储位置编号,是一个常量. 2.指针:指针的本质就是地址. 指针变量的定义和声明 1.指针变量:存储的数据是地址. 2.定义方法:类型* ...
- 3Des加密解密,java c#通用。
1.需要实现对其他系统的单点登陆,我们实现的方法很简单,就是将当前系统的账号通过加密去获取 需要直接登陆上的系统的token,然后访问需直接登陆的系统就带着token,就相当于登陆了. 2.然后呢,我 ...
- 针对“RuntimeError: each element in list of batch should be of equal size” 问题解决
第一次运行代码出现了这个问题: 这个问题的出现主要来源于DataLoader类中的collate.py文件造成的问题,由于每个batch里的长度不一致,因此导致出现了该问题. 通过百度方法和查看源码去 ...
- python发布定时任务(schedule模块)
最近公司开始让在自己开发的软件上写日志,有几次下班了都忘了写,好几次都是给领导发邮件,说明一下自己没有写日志这件事,很麻烦.但是我一想我每天都要写,岂不是很麻烦,想想自己之前有爬虫经验,为什么自己不写 ...