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


本讲我们设计一个简单的读硬盘实验。通过一定的方法使硬盘第二个扇区的前3个字节依次为1、2、3,最后3个字节依次为3、2、1,中间的506个字节全为0。然后通过读硬盘程序将硬盘第二个扇区的数据读取到内存0x7e00-0x7fff的地方,也就是内存中MBR之后的512个字节。最后通过QEMU+DGB调试的方式来查看内存中0x7e00-0x7fff的数据,是否与硬盘第二个扇区中的数据一致,如果一致说明读硬盘成功。

本讲代码文件共2个:

  • data1.asm
  • boot1.asm

下面我们开始实验。

一、设置硬盘第二个扇区中的数据

data1.asm代码如下:

db 1
db 2
db 3
times 506 db 0
db 3
db 2
db 1

data1.asm就是生成512字节的数据,前3个字节依次是1、2、3,最后3个字节依次为3、2、1,中间的506个字节全为0。

在PowerShell中输入如下命令:

nasm data1.asm -o data1.bin
hexdump data1.bin -C

上述命令是将data1.asm通过汇编器生成了二进制文件data1.bin,然后通过hexdump命令查看data1.bin是否正确。截图如下:

从上面截图可以看到,生成的data.bin文件共512字节,其中前3个字节依次为1、2、3,最后3个字节依次为3、2、1,中间的506个字节全为0。下面将data1.bin文件写入到虚拟硬盘的第二个扇区中。

在PowerShell中输入如下命令:

dd conv=notrunc if=data1.bin of=/media/VMShare/GrapeOS.img seek=1
hexdump /media/VMShare/GrapeOS.img -C

上面dd命令中的参数seek=1意思是在写入GrapeOS.img时,跳过1个写入块,写入块默认大小为512字节,也就将data1.bin写入到虚拟硬盘GrapeOS.img的第二个扇区中。截图如下:

从上面截图中可以看到,虚拟硬盘第二个扇区中的数据达到了我们的实验要求。

二、读硬盘程序

boot1.asm的代码如下:

;定义常量
DISK_BUFFER equ 0x7e00 ;读硬盘临时存放数据用的缓存区,放到boot程序之后。 org 0x7c00 ;初始化段寄存器
mov ax,cs
mov ds,ax ;ds指向与cs相同的段 mov esi,1 ;读取硬盘的第2个扇区
mov di,DISK_BUFFER
call func_read_one_sector stop:
hlt
jmp stop ;读取硬盘1个扇区(主硬盘控制器主盘)
;输入参数:esi,ds:di。
;esi LBA扇区号
;ds:di 将数据写入到的内存起始地址
;输出参数:无。
func_read_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,esi
;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端口写入读命令0x20
mov dx,0x1f7
mov al,0x20
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_read:
in ax,dx
mov [di],ax
add di,2
loop .go_on_read
ret times 510-($-$$) db 0
db 0x55,0xaa

上面的代码主要就是读硬盘函数func_read_one_sector,总共分7个步骤,与上讲中的读硬盘操作步骤一致。结合代码注释和之前讲的知识,大家应该是可以看懂的。

下面我们将编译boot1.asm,并将生成的二进制文件写入到虚拟硬盘的第一个扇区。在PowerShell中输入如下命令:

nasm boot1.asm -o boot1.bin
dd conv=notrunc if=boot1.bin of=/media/VMShare/GrapeOS.img

截图如下:

在Windows的cmd命令行中启动QEMU调试模式:

qemu-system-i386 d:\GrapeOS\VMShare\GrapeOS.img -S -s

截图如下:

在PowerShell中启动GDB:

[root@CentOS7 Lesson20]# gdb
(gdb) target remote 192.168.10.102:1234
(gdb) b *0x7c00
(gdb) c
Continuing. Breakpoint 1, 0x00007c00 in ?? ()
(gdb) x /512xb 0x7e00

截图如下:

从截图中可以看到,此时程序停在了断点0x7c00处,此时内存中0x7e00-0x7fff中的数据都是0。

我们输入命令c,让程序继续运行几秒钟,然后Ctrl+C,让程序暂停。此时读硬盘程序应该已经执行完了,我们再来查看一下内存0x7e00-0x7fff中的数据。截图如下:

从截图中可以看到,此时内存中0x7e00-0x7fff的数据和硬盘第二扇区中的数据一致,说明读取成功,实验完毕。


本讲视频版地址:https://www.bilibili.com/video/BV1JY411z7VT/

配套的代码与资料在:https://gitee.com/jackchengyujia/grapeos-course

GrapeOS操作系统交流QQ群:643474045

自己动手从零写桌面操作系统GrapeOS系列教程——20.汇编语言读硬盘实战的更多相关文章

  1. 别人写的一个Bootstrap系列教程

    http://www.cnblogs.com/lansy/category/659061.html

  2. 一个人写的操作系统 - Sparrow OS

    一个人写的操作系统 - Sparrow OS 自己写一个操作系统,这是在过去的几年里我一直为之努力的目标,现在终于完成了. 缘起 自己动手写操作系统的动机最初来自于学习Linux遇到的困难. 我是一个 ...

  3. 自制 os 极简教程1:写一个操作系统有多难

    为什么叫极简教程呢?听我慢慢说 不知道正在阅读本文的你,是否是因为想自己动手写一个操作系统.我觉得可能每个程序员都有个操作系统梦,或许是想亲自动手写出来一个,或许是想彻底吃透操作系统的知识.不论是为了 ...

  4. 【操作系统】关于Linux桌面操作系统

    以前是Win+Ubuntu+黑苹果,周末想体验一下deepin,于是简单安装了一下,安装过程很简单,这里不再描述.安装之后,第一次打开系统,确实很惊艳,赏心悦目的操作系统. 之前用Ubuntu时候,C ...

  5. 盘点|2021年最受欢迎Linux桌面操作系统前十名

    镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 阿里云开源镜像站利用云服务上的优势,提供快速.稳定的镜像分发服务.和免费的CDN加速服务.更新频率高,基本上一天一更新,对于Centos/Ubun ...

  6. 手把手教你从零写一个简单的 VUE

    本系列是一个教程,下面贴下目录~1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 今天给大家带来的是实现一个简单的类似 VUE 一样的前端框架,VUE 框架现在应 ...

  7. 《一步一步写嵌入式操作系统》读书笔记1—Skyeye介绍、安装和HelloWorld

    2013-11-14 最近在看<一步一步写嵌入式操作系统>,感觉此书甚好,许多地方讲得很清楚.可操作性强,计划边读边实践边写笔记,希望能够逐步熟悉嵌入式操作系统底层的东西,最终剪裁出一套实 ...

  8. Python之美[从菜鸟到高手]--一步一步动手给Python写扩展(异常处理和引用计数)

    我们将继续一步一步动手给Python写扩展,通过上一篇我们学习了如何写扩展,本篇将介绍一些高级话题,如异常,引用计数问题等.强烈建议先看上一篇,Python之美[从菜鸟到高手]--一步一步动手给Pyt ...

  9. Zedboard学习(一):移植Ubuntu桌面操作系统 标签: ubuntu移植zedboardFPGA 2017-07-04 21:53 26人阅读

    环境准备: 首先,需要的肯定是Ubuntu操作系统.可以在自己的电脑上安装物理机,也可以是虚拟机下运行的.我的是在Vmware下运行的Ubuntu14.04 32位操作系统. 由于zedboard上的 ...

  10. 27、从零写UVC驱动之分析数据传输(设置ubuntu通过串口打印,指定打印到文件,ubuntu切换root用户)

    A. 设置ubuntu让它从串口0输出printk信息a. 设置vmware添加serial port, 使用文件作为串口(在vmware中设置,文件是保存在windows中)b. 启动ubuntu, ...

随机推荐

  1. labwindows excel 不同电脑上无法保存

    存到c盘以外的盘,c盘因为权限问题可能无法写入

  2. 我的第一周C语言作业

    这个作业属于哪个课程 https://edu.cnblogs.com/campus/zswxy/SE2020-2 这个作业要求在哪里 https://edu.cnblogs.com/campus/zs ...

  3. libevent学习之入门--[01]概述与安装

    网上关于libevent的介绍不在少数,我相信目前看到我这篇博客时已经基本了解libevent是用来做什么的,有什么功能,在此就不重复介绍了.我会按照我学习的过程来完整记录整个库的所有核心内容和具体应 ...

  4. bzoj 4407

    莫比乌斯反演 还是推式子: 设$f(n)=n^{k}$ 那就是上一道题了 推的过程如下: $\sum_{i=1}^{a}\sum_{j=1}^{b}f(gcd(i,j))$ $\sum_{i=1}^{ ...

  5. js 复制链接内容

    <script type="text/javascript">//复制活动地址 function shareUrl(id) { var url = 'http://H5 ...

  6. CORS(cross origin resource sharing)

    1.什么是CORS 定义:跨域资源共享. 2.什么是跨域资源共享 允许浏览器可以从当前源服务器通过ajax访问另外一个源服务地址. 3.同源策略 是浏览器的一个安全功能,不同源的客户端脚本在没有明确的 ...

  7. 如何简单使用Git

    Git基本功能 Git基本功能 在具体介绍Git能做什么之前,先来了解下Git里的四个角色: workspace: 本地的工作空间. index:缓存区域,临时保存本地改动. local reposi ...

  8. LeetCode 之 108. 将有序数组转换为二叉搜索树

    原题链接 思路: 二叉搜索树的定义: 它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的 ...

  9. X射线随笔

    2023-02-27 千里马与伯乐 如果把X射线(X光)比做千里马的话,那这匹千里马的发掘,离不开伯乐的贡献.说起X射线的伯乐,就得从一个简短的故事说起: 1895年11月8日的夜晚,德国物理学家伦琴 ...

  10. swftools工具将pdf文件转换为swf文件 文字丢失

    开发客户网站时遇到了一个需求,客户要求后台上传pdf文件,前台能以翻书的形式直接访问. 首先想到的是使用js解决,用户访问前端页面时,php将文件路径发送给js,让js呈现出来翻书的效果.在网上百度了 ...