自己动手从零写桌面操作系统GrapeOS系列教程——13.向MBR中写入程序
学习操作系统原理最好的方法是自己写一个简单的操作系统。
前面铺垫了这么久,今天终于开始写程序了。本讲将介绍3个逐步深入但非常简单的程序,一方面是让大家熟悉开发流程,另一方面是顺便解决前面遇到的CPU占用率高的问题。
一、mbr1.asm回顾
mbr1.asm的代码之前我们介绍过,这里我们回顾一下代码和演示步骤。
mbr1.asm代码如下:
;生成一个空的MBR
times 510 db 0 ;前510个字节全为0
db 0x55,0xaa ;最后两个字节是0x55和0xaa。
下面我们来演示:
1.启动并登录CentOS
在VirtualBox中启动CentOS虚拟机,并用PowerShell登录到CentOS虚拟机。
2.创建空虚拟硬盘
如果没有虚拟硬盘或想重新创建一个空的虚拟硬盘,执行下面这条语句:
dd if=/dev/zero of=/media/VMShare/GrapeOS.img bs=1M count=4
截图如下:
在上面截图中,用hexdump命令查看生成的虚拟硬盘文件GrapeOS.img,可以看到每个字节都是0,符合预期。
3.汇编mbr1.asm
nasm mbr1.asm -o mbr1.bin
截图如下:
在上面截图中,用hexdump命令查看生成的mbr1.bin,共512个字节,前510个字节都是0,最后两个字节是0x55和0xaa,符合预期。
4.将mbr1.bin写入到虚拟硬盘中
dd conv=notrunc if=mbr1.bin of=/media/VMShare/GrapeOS.img
截图如下:
在上面截图中,我们同样用hexdump命令验证,看到的确是将mbr.bin写入到虚拟硬盘的第一个扇区中了。
5.启动QEMU
在Windows的cmd命令行中运行如下命令:
qemu-system-i386 d:\GrapeOS\VMShare\GrapeOS.img
从截图上可以看到,运行结果和之前的一样。回顾到此为止,下面来解决CPU占用率高的问题。
二、CPU占用率高的原因
前面我们介绍过,在QEMU+GDB调试中,反编译16位代码是有问题的,下面来介绍另一种反编译方法。nasm汇编器自带了一个反汇编工具叫ndisasm,下面我们来反汇编mbr1.bin。
ndisasm mbr1.bin
截图如下:
从截图中可以看到两个0字节正好是一条汇编指令“add [bx+si],al”,最后的2个字节0x55和0xaa也正好是指令“push bp”和“stosb”。但这些都不是我们要写的程序,只是这些二进制数正好是某条机器指令。从BIOS跳转到0x7c00地址后,无论此处是什么样的二进制数,CPU都会把它当作指令一条一条的执行。当执行完这512字节,会继续执行后面内存中的数据。而后面内存中的数据是不确定的,CPU就会乱执行半天,而且也没有意义,这就是程序跑飞了。下面我们先来解决程序跑飞的问题。
三、mbr2.asm阻止程序跑飞
1.程序讲解
mbr2.asm代码如下:
jmp $ ;$表示当前行的地址
times 510-($-$$) db 0 ;$$表示段开始的地址,$-$$表示当前行前面的代码占用的字节数。
db 0x55,0xaa
在Linux命令行中执行如下命令:
nasm mbr2.asm -o mbr2.bin
hexdump mbr2.bin -C
ndisasm mbr2.bin
从上面截图中可以看到“jmp $”生成的机器码是“0xeb,0xfe”,其中0xeb是操作码,0xfe是操作数。这条指令中的操作数是当作有符号数处理的,0xfe换算成十进制数是“-2”(负2)。而这条指令共2个字节,当CPU读取完这条指令后寄存器ip的值会加2,执行完这条指令后,寄存器ip的值会加负2。这样的话CPU就会不断的重复执行这条指令,程序就不会跑飞了。
2.程序演示
下面我们将mbr2.bin写入到虚拟硬盘的第一个扇区。
dd conv=notrunc if=mbr2.bin of=/media/VMShare/GrapeOS.img
hexdump /media/VMShare/GrapeOS.img -C
然后用调试模式观察一下。
qemu-system-i386 d:\GrapeOS\VMShare\GrapeOS.img -S -s
前面我们介绍过,这里GDB是按32位反汇编的,16位反汇编是有问题的。但有些汇编代码在16位和32位下生成的机器码是一样的,比如这里的jmp $
。所以这里的反汇编也可以适当参考一下。从上面截图上可以看到,每次单步运行后,程序地址仍然停留在0x7c00。这就是通过死循环来防止程序跑飞的办法。
下面我们来删除断点,让程序正常运行。
首先来查看断点:
(gdb) i b
删除断点:
(gdb) d 断点编号
然后让程序继续运行:
(gdb) c
截图如下:
mbr2.asm虽然解决了程序跑飞的问题,但CPU占用率仍然高,笔记本风扇还是呼呼的转。下面我们来彻底解决这个问题。
四、mbr3.asm彻底解决CPU占用率高的问题
mbr3.asm的代码如下:
stop:
hlt ;使CPU暂停运行,直到有中断发生。(降低CPU使用率)
jmp stop
times 510-($-$$) db 0
db 0x55,0xaa
上述代码主要用了一个hlt
指令,让CPU暂停,如果有中断发生,会执行下一行jmp stop
,然后又执行hlt
。这样不仅防止了程序跑飞,而且降低了CPU使用率。
有了前面的基础,我们这次编译运行一气呵成。
在Linux命令行中执行:
nasm mbr3.asm -o mbr3.bin
dd conv=notrunc if=mbr3.bin of=/media/VMShare/GrapeOS.img
在Windows命令行中执行:
qemu-system-i386 d:\GrapeOS\VMShare\GrapeOS.img
截图如下:
从上图任务管理器中可以看到,QEMU的CPU占用率已经降下来了。
本讲视频版地址:https://www.bilibili.com/video/BV1io4y1i7GP/
本教程代码和资料:https://gitee.com/jackchengyujia/grapeos-course
GrapeOS操作系统QQ群:643474045
自己动手从零写桌面操作系统GrapeOS系列教程——13.向MBR中写入程序的更多相关文章
- 操作系统开发系列—12.f.在内核中添加中断处理 ●
因为CPU只有一个,同一时刻要么是客户进程在运行,要么是操作系统在运行,如果实现进程,需要一种控制权转换机制,这种机制便是中断. 要做的工作有两项:设置8259A和建立IDT. /*========= ...
- 操作系统开发系列—12.g.在内核中设置键盘中断
8259A虽然已经设置完成,但是我们还没有真正开始使用它呢. 所有的中断都会触发一个函数spurious_irq(),这个函数的定义如下: PUBLIC void spurious_irq(int i ...
- 别人写的一个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 ...
- 手把手教你从零写一个简单的 VUE
本系列是一个教程,下面贴下目录~1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 今天给大家带来的是实现一个简单的类似 VUE 一样的前端框架,VUE 框架现在应 ...
- 《一步一步写嵌入式操作系统》读书笔记1—Skyeye介绍、安装和HelloWorld
2013-11-14 最近在看<一步一步写嵌入式操作系统>,感觉此书甚好,许多地方讲得很清楚.可操作性强,计划边读边实践边写笔记,希望能够逐步熟悉嵌入式操作系统底层的东西,最终剪裁出一套实 ...
- Python之美[从菜鸟到高手]--一步一步动手给Python写扩展(异常处理和引用计数)
我们将继续一步一步动手给Python写扩展,通过上一篇我们学习了如何写扩展,本篇将介绍一些高级话题,如异常,引用计数问题等.强烈建议先看上一篇,Python之美[从菜鸟到高手]--一步一步动手给Pyt ...
随机推荐
- 网络图片转InputStream,网络图片转MultipartFile,InputStream转MultipartFile
头疼,不废话直接上代码 <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> ...
- 「SOL」E-Lite (Ural Championship 2013)
为什么这数据能水到可以枚举角度 ac 啊 # 题面 给你 \(n\) 个平面向量 \((x_i,y_i)\),对于每个 \(k=1\sim n\),求「从给出的 \(n\) 个向量中不重复地选择 \( ...
- Tomcat put 漏洞批量工具
工具下载 https://share.weiyun.com/96ffd3bf26b09ffece8d01317f3b3efb
- 5 hashlib模块
import hashlib def gen_md5(origin): """md5加密""" ha = hashlib.md5(b'lkp ...
- bzoj 2337
有人说这题像游走... 关于游走的思想,他死了... 明明直接从期望dp的角度考虑更简单合理嘛 首先由于是异或运算不妨逐位考虑 对于每一位,设状态$f[i]$表示从第$i$个点到第$n$个点,这一位上 ...
- Docker基本命令之 仓库管理(docker hub)
仓库管理 仓库介绍:仓库(Repository)就是集中存放镜像的地方 登录docker hub注册一个自己的账号 然后创建一个仓库:xxx 登录:docker login -- 输入用户名/密码(退 ...
- K8s 与 Service Mesh(服务与流量治理)
K8s相关资料可参考链接: Kubernetes简介 1 什么是Service Mesh Service Mesh 是一个专门处理服务通讯的基础设施层.它的职责是在由云原生应用组成服务的复杂拓扑结构 ...
- window 版本下面建立linux命令行终端的方法
这个主要是解决dos系统命令行与linux命令行不匹配的问题. 因此microsoft shop 中开发了很多免费的app可供傻瓜式的安装使用.但是出现了不能下载的问题. 链接如下:https://w ...
- 六、js创建页码器:分页、上一页下一页、省略页码
表格数据太多,需要做成分页.因此需要写一个页码器. 1,初始化页码 获取数据之后渲染页码器,页码器初始化,小于6页的全部展示,否则展示前四页,后面是省略号,最后展示尾页.默认选中第一页,禁用前一页的箭 ...
- Python pexpect 库的简单使用
一.Python pexpect 库的使用 在终端中许多命令都有与用户交互的场景,例如切换用户时需要手动输入密码,安装应用有时要输入默认配置等.这对 shell 自动化脚本十分不便.expect 命令 ...