首页 > 编程语言 >自己动手从零写桌面操作系统GrapeOS系列教程——21.汇编语言写硬盘实战

自己动手从零写桌面操作系统GrapeOS系列教程——21.汇编语言写硬盘实战

时间:2023-03-22 11:03:25浏览次数:52  
标签:21 写入 mov al GrapeOS 桌面操作系统 扇区 dx 硬盘

学习操作系统原理最好的方法是自己写一个简单的操作系统。


在上一讲中我们学习了用汇编语言读硬盘,本讲我们来学习用汇编语言写硬盘。同样也是设计一个简单的实验,实验内容为:

在内存中准备一段有特征的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

标签:21,写入,mov,al,GrapeOS,桌面操作系统,扇区,dx,硬盘
From: https://www.cnblogs.com/chengyujia/p/17242788.html

相关文章

  • 踩坑纪实:UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 21-22:
    问题出现过程切换新的服务器之后,使用PyExecJS库报错...ctx=execjs.compile(js_str)version_obj=ctx.eval('exportObj')报错内容:UnicodeDecodeError:'utf-8'co......
  • 软件工程3月21日结队日报
    学习时间:五小时代码量:800博客量:1任务:今天对地铁查询系统PC端的前端页面进行了一些css与js的美化,并且完成了安卓端的查询线路、查询站点的功能,对于起点---终点查询也完成......
  • 3月21日
    AndroidStudio提供了更加高级的布局文件编辑器,(1)我们在编写XML文件的时候,能实时查看布局文件。(2)能直接以拖控件的方式编辑布局文件。当然这些Eclipse也有。   只有这......
  • 2023.3.21晚报
    1.英语元音发音2.算法:红蓝白三色球排序(题目就不写了,leetcode上有)解法思路:对0,1生成两个指针,遍历数组,当数组数目不为指针所指向数字时向后遍历,与指向数字相等时则与当前指......
  • 3/21人月神话读书笔记
    作为开章第一篇,就先来说说为什么“人月”是“神话”。小学的时候我们都做过这样的应用题:“工厂需要加工一批零件,安排5名工人的话需要10小时完成,那么安排25名工人加工,多少......
  • 每日总结2023/3/21
    今天进行了Android的地铁查询操作,主要是进行了简单的前两步,线路和站点查询,并为Android安装了搜狗输入法,以保障汉字的输入。代码行大概50 优化更改textview使之高度变......
  • 3.21博客
    总结:1.完成python的pta练习主要问题:6-2计算时一直报错非零返回本题要求计算输入两个正整数x,y(x<=y,包括x,y)素数和。函数isPrime用以判断一个数是否素数,primeSum函数返......
  • day21 (2023.3.21)
    1.迭代List接口类型容器 运行结果: 2.迭代Set接口类型容器 运行结果: 3.迭代Map接口类型容器 运行结果: 4.在迭代器中删除元素: 运行结果: 5.操......
  • 每日总结 3.21
    今天进行了Android的地铁查询操作,主要是进行了简单的前两步,线路和站点查询,并为Android安装了搜狗输入法,以保障汉字的输入。代码行大概50 优化更改textview使之高度变......
  • 2023/3/21
    今天最大的进度,就是配置好安卓的PDF的开源库。之前找了很长时间的开源库,但是往往就是配置依赖的时候死掉。不仅仅需要在build.gradle里面导入依赖。而且还需要在setting.gr......