旭翔汽车蓄电池 發表於 2023-3-22 10:51:00

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

<blockquote>
<p><em>学习操作系统原理最好的方法是自己写一个简单的操作系统。</em></p>
</blockquote>
<hr>
<p>在上一讲中我们学习了用汇编语言读硬盘,本讲我们来学习用汇编语言写硬盘。同样也是设计一个简单的实验,实验内容为:</p>
<pre><code>在内存中准备一段有特征的512字节数据,地址为0x7e00~0x7fff,其特征是前3个字节依次为4、5、6,最后3个字节依次为6、5、4。然后将该段内存数据写入到硬盘的第2个扇区,并查看虚拟硬盘第2个扇区的数据是否与内存中0x7e00~0x7fff的数据一致,如果一致则说明写硬盘成功。
</code></pre>
<p>本讲代码文件只有一个<code>boot2.asm</code>。<br>
boot2.asm代码如下:</p>
<pre><code class="language-X86ASM">;定义常量
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 ,4
mov byte ,5
mov byte ,6
;向缓存区最后3个字节依次写入6、5、4。
mov byte ,6
mov byte ,5
mov byte ,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,
out dx,ax
add si,2
loop .go_on_write
ret

times 510-($-$$) db 0
db 0x55,0xaa
</code></pre>
<p>之前我们介绍过读硬盘操作和写硬盘操作都是7个步骤,其中只有第5步和第7步不同,其它步骤完全相同,大家可以和上一讲中的代码对比看一下。<br>
下面我们将boot2.asm编译并写入到虚拟硬盘的第一个扇区:</p>
<pre><code>nasm boot2.asm -o boot2.bin
dd conv=notrunc if=boot2.bin of=/media/VMShare/GrapeOS.img
</code></pre>
<p><img src="https://img2023.cnblogs.com/blog/343777/202303/343777-20230322104045261-598246851.png" alt="" loading="lazy"></p>
<p>此时用hexdum命令查看一下虚拟硬盘第二个扇区当前的数据,截图如下:<br>
<img src="https://img2023.cnblogs.com/blog/343777/202303/343777-20230322104055921-857472481.png" alt="" loading="lazy"></p>
<p>从上面的截图可以看到,此时虚拟硬盘第二个扇区前3个字节依次为1、2、3,最后3个字节依次为3、2、1。<br>
下面我们以调试模式运行QEMU:</p>
<pre><code>qemu-system-i386 d:\GrapeOS\VMShare\GrapeOS.img -S -s
</code></pre>
<p><img src="https://img2023.cnblogs.com/blog/343777/202303/343777-20230322104105114-1734023521.png" alt="" loading="lazy"></p>
<p><img src="https://img2023.cnblogs.com/blog/343777/202303/343777-20230322104111090-993206351.png" alt="" loading="lazy"></p>
<p>通过GDB连接到QEMU,直接输入GDB命令<code>c</code>,让程序运行几秒钟,然后Ctrl+C,让程序暂停。此时写硬盘程序应该已经运行完了。此时查看一下内存0x7e00~0x7fff的数据:</p>
<pre><code>(gdb) x /512xb 0x7e00
</code></pre>
<p><img src="https://img2023.cnblogs.com/blog/343777/202303/343777-20230322104119546-333679495.png" alt="" loading="lazy"></p>
<p><img src="https://img2023.cnblogs.com/blog/343777/202303/343777-20230322104125039-1005750406.png" alt="" loading="lazy"></p>
<p>从上面截图可以看到,在内存0x7e00~0x7fff的数据中,前3个字节依次为4、5、6,最后3个字节依次为6、5、4,其余全是0。如果程序运行正确的话,此时硬盘第二扇区中的数据与此相同。<br>
下面我们退出GDB,并关闭QEMU。然后用hexdum命令再查看一下虚拟硬盘第二个扇区的数据,截图如下:<br>
<img src="https://img2023.cnblogs.com/blog/343777/202303/343777-20230322104135561-1435789572.png" alt="" loading="lazy"></p>
<p>从上面截图中可以看到,硬盘第二扇区的数据与内存中0x7e00~0x7fff的数据一致,说明写入成功,实验完毕。</p>
<hr>
<p>本讲视频版地址:https://www.bilibili.com/video/BV1Hk4y187Bw/<br>
配套的代码与资料在:https://gitee.com/jackchengyujia/grapeos-course<br>
GrapeOS操作系统交流QQ群:643474045</p>


</div>
<div id="MySignature" role="contentinfo">
    <div style="border-style: solid; border-color: #666; border-width: 1px; background-color: #E6FAE6; color: #000; padding: 10px;">
作者:成宇佳<br>
博客主页:http://www.cnblogs.com/chengyujia/<br>
欢迎转载,但请保留作者和本文链接,谢谢!<br>
欢迎在下面的评论区与我交流。<br>
<div style="color: #F00">
如果觉得写的不错,请点击下面的“推荐”按钮,让我更有动力写出更好的文章。
</div>
</div><br><br>
来源:https://www.cnblogs.com/chengyujia/p/17242788.html
頁: [1]
查看完整版本: 自己动手从零写桌面操作系统GrapeOS系列教程——21.汇编语言写硬盘实战