手写简易操作系统(二)--启动计算机

前情提要

在上一部分的内容中,我们已经做好了模拟仿真的整个准备工作,这一节我们就先把计算机启动起来。

一、Bochs配置

1.1、配置启动盘

创建硬盘的工具是bximage,这个工具在我们的Bochs目录下,使用命令行创建硬盘

image-20240309173637499

第一个选择 1,即创建新的硬盘或者软盘

第二个选择 hd,即创建硬盘

第三个选择 flat,即创建flat格式的硬盘,还有一些诸如sparse, growing, vpc or vmware4格式的硬盘。

第四个选择 512,即一个扇区有512字节

第五个选择 60,即硬盘的大小为60MB

第六个选择 hd60M.img,这个是硬盘的名字

1.2、配置启动文件

在bin目录下新建一个启动文件 bochsrc.disk

# 设置内存为32MB
megs: 32# 设置对应机器的BIOS
romimage: file=/home/lyj/bochs/share/bochs/BIOS-bochs-latest 
# 设置对应机器的VGA BIOS
vgaromimage: file=/home/lyj/bochs/share/bochs/VGABIOS-lgpl-latest # 选择启动盘符,默认为从软盘启动,但是这里设置为硬盘,软盘太古老了
boot: disk # 设置日志文件的输出
log: bochs_out.log# 关闭鼠标功能,打开键盘功能,并且设置键盘的映射
mouse: enabled=0 
keyboard: keymap=/home/lyj/bochs/share/bochs/keymaps/x11-pc-us.map # 硬盘设置
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 
ata0-master: type=disk, path="/home/lyj/bochs/bin/hd60M.img", mode=flat

其中的大部分设置都做了详细的注释,这里我们对硬盘部分做出一些更详细的解释

  • enabled=1:表示 ATA0 控制器被启用。这意味着 Bochs 将会模拟一个 ATA0 控制器,并允许虚拟机使用这个控制器来访问硬盘或光驱设备。

  • ioaddr1=0x1f0:表示 ATA0 控制器的 I/O 端口地址。在计算机体系结构中,I/O 端口用于与外部设备进行数据交换。这里指定了 ATA0 控制器的主要 I/O 端口地址为 0x1f0。

  • ioaddr2=0x3f0:表示 ATA0 控制器的备用(secondary)I/O 端口地址。有些设备可能需要额外的 I/O 端口进行通信,这里指定了 ATA0 控制器的备用 I/O 端口地址为 0x3f0。

  • irq=14:表示 ATA0 控制器的中断请求线(IRQ)。中断请求线用于处理硬件设备发出的中断信号,这里指定了 ATA0 控制器的中断请求线为 14。

ata0可以挂载两个硬盘,其中一个是主盘一个是从盘。这部分内容我们会在讲解硬盘时详细说。

1.3、启动Bochs

./bochs -f bochsrc.disk

在bochs的命令行中先输入 6,即开始仿真

在输入 c,即开始执行

然后我们就看到了下面的画面

image-20240309173917596

系统提示没有可引导的启动设备,也就是我们设置的硬盘是一个空的硬盘,里面并没有程序可以执行,所以直接报错退出了。接下来我们让整个程序先能跑起来。

二、MBR主引导记录

好了,我们要开始写代码了,在写代码之前先普及一点小知识,x86架构的处理器,由于历史原因,一开始是先进入实模式,再进入保护模式的。实模式下,只有20根地址线,因此只能访问到2的20次方Byte的数据,也就是1MB。这1MB又被分为了几个部分,我们可以看一下

image-20240309193017875

这一部分如果我们学过《汇编语言》或者《微机原理》之类的课程是比较好理解的

2.1、BIOS启动

开机的一瞬间,BIOS被启动,BIOS中的代码就存在于 0xF0000~0xFFFFF 这个地址了,但实际上这个地址不是内存,是的,你没听错,不是内存,是一块ROM。

为了统一管理计算机中的端口,内存,ROM等等设备,计算机将这些东西统一了,就像访问内存那样去访问这些资源。

所以在开机的一瞬间,CPU的cs:ip寄存器被强制初始化为0xF000:0xFFF0,这样就可以直接执行BIOS中的程序。BIOS开始检测内存,显卡等外设信息,当外设准备好后,开始在 0x000~0x3FF 处建立中断向量表,这些中断就是BIOS提供的基础功能,可以帮助我们操作系统做一些基础操作。

做完这些,BIOS的使命就要结束了,最后的一点任务,校验启动盘中位于0盘0道1扇区(也就是LBA地址为0的扇区)的内容,如果此扇区末尾的两个字节分别是魔数 0x550xaa,BIOS便认为此扇区中确实存在可执行的程序,并把这个扇区的内容加载到物理地址 0x7c00 的内存中,一个扇区的大小我们在上一节中设置硬盘扇区大小中设置过了,是512B。

最后BIOS通过跳转指令 jmp 0:0x7c00 跳转到 0x7c00 的地址开始执行用户的程序,这里用户的程序也就是我们的操作系统了。

问:为什么是魔数 0x550xaa

答:BIOS中设置好的,也是大家公认的,如果你自己写BIOS的话,也可以设置为别的,但是这就不通用了。

问:为什么是 0x7c00 的地址?

答:这也是一个写死了的地址,王八的屁股,规定。

2.2、编写MBR,并编译

这里我们还是用到了BIOS中自带的中断。代码如下所示

; os/src/boot/mbr.s
; 设置开始的地址,并且初始化寄存器
SECTION MBR vstart=0x7c00         mov ax,cs      mov ds,axmov es,axmov ss,axmov fs,axmov sp,0x7c00; 利用0x06号功能实现清理屏幕
; AL = 0x06 功能号
; AL 上卷的行数(如果为0,表示全部)
; BH 上卷行属性
; (CL,CH) = 窗口左上角的(X,Y)位置,这里是 (0,0)
; (DL,DH) = 窗口右下角的(X,Y)位置,这里是 (80,25)mov    ah, 0x06mov    al, 0x00mov    bh, 0x7mov    bl, 0x00mov    cx, 0           mov    dx, 0x184fint    0x10            ; int 0x10; 获取光标位置 
; AL = 0x03 功能号
; bh 寄存器存储的是待获取光标的页号mov    ah, 3mov    bh, 0int    0x10; 打印字符串
; BP 字符串地址,BP需要通过AX访问,不能直接给BP内存数据
; AL = 0x13 功能号
; AL = 0x01 显示字符串,光标跟随移动
; CX = 0x03 字符串长度
; BH = 0x00 要显示的页号
; BL = 0x02 字符属性,属性黑底绿字mov ax, messagemov bp, axmov ax, 0x1301mov cx, 0x03mov bx, 0x02int 0x10	; 循环等待jmp $            
; 要显示的字符串message db "MBR"
; 将510个字节中剩余的空间填充为0
; $ 是当前地址
; $$ 是本节开头地址,也就是0x7c00times 510-($-$$) db 0db 0x55,0xaa

其实还是很简单的,就像是调用函数,然后我们往那些指定的寄存器中添加数据就可以了。

编译一下

nasm -o bin/mbr.bin src/boot/mbr.s

查看一下确实是512字节

image-20240309201604822

然后我们将这个文件直接通过dd指令存放到我们之前生成的虚拟硬盘中的0盘0道1扇区

dd if=./bin/mbr.bin of=~/bochs/bin/hd60M.img bs=512 count=1 conv=notrunc

然后运行Bochs

~/bochs/bin/bochs -f ~/bochs/bin/bochsrc.disk

可以看到,我们成功的运行起来了

image-20240309202030610

2.3、改进MBR,直接操作显卡

我们将输出字符串直接通过操作显存来完成。通过上表我们可以得知,显存是从0xB8000~0xBFFFF,范围是32KB,一屏可以显示2000个字符,显示器上的每个字符占2字节大小,故每屏字符实际占用4000字节。这样,我们的32KB的显存可以容纳8屏的数据。

屏幕上每个字符的低字节是字符的ASCII码,高字节是字符属性元信息。

image-20240309204513916

其中各个位的搭配为

image-20240309210135540

我们将程序修改为

; os/src/boot/mbr.s
; 设置开始的地址,并且初始化寄存器
SECTION MBR vstart=0x7c00         mov ax,cs      mov ds,axmov es,axmov ss,axmov fs,axmov sp,0x7c00mov ax,0xb800mov gs,ax; 利用0x06号功能实现清理屏幕
; AL = 0x06 功能号
; AL 上卷的行数(如果为0,表示全部)
; BH 上卷行属性
; (CL,CH) = 窗口左上角的(X,Y)位置,这里是 (0,0)
; (DL,DH) = 窗口右下角的(X,Y)位置,这里是 (80,25)mov    ah, 0x06mov    al, 0x00mov    bh, 0x7mov    bl, 0x00mov    cx, 0           mov    dx, 0x184fint    0x10             ; int 0x10mov byte [gs:0x00],'M'  ; 字符为M的ascii值mov byte [gs:0x01],0x0F	; 00001111b 即背景色为黑,字体为白,不闪烁 mov byte [gs:0x02],'B'  ;mov byte [gs:0x03],0x0F	; mov byte [gs:0x04],'R'  ;mov byte [gs:0x05],0x0F	;; 循环等待jmp $            
; 要显示的字符串message db "MBR"
; 将510个字节中剩余的空间填充为0
; $ 是当前地址
; $$ 是本节开头地址,也就是0x7c00times 510-($-$$) db 0db 0x55,0xaa

之前的编译,写入硬盘,启动程序,这里也可以简单点写个脚本

# os/run.sh
# 编译mbr
nasm -o bin/mbr.bin src/boot/mbr.s # 复制mbr二进制程序到硬盘
dd if=./bin/mbr.bin of=/home/lyj/bochs/bin/hd60M.img bs=512 count=1 conv=notrunc# 启动仿真
/home/lyj/bochs/bin/bochs -f /home/lyj/bochs/bin/bochsrc.disk 

直接启动脚本

image-20240309210444176

结束语

好了第二章已经结束了,这一章我们生成了需要的硬盘以及写了一个简单的MBR引导程序,但是我们的内核还在硬盘中(实际上还没有写),下一章我们将在MBR中实现一个内核加载器出来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/272380.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解数据库、Hive以及Hadoop之间的关系

1.数据库: 数据库是一个用于存储和管理数据的系统。数据库管理系统(DBMS)是用于管理数据库的软件。数据库使用表和字段的结构来组织和存储数据。关系型数据库是最常见的数据库类型,使用SQL(Structured Query Language…

登录校验认证

会话技术 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。 会话跟踪: 一种维护浏览器状态的方法,服务器需要识别多次请…

【Web】浅聊Java反序列化之Rome——关于其他利用链

目录 前言 JdbcRowSetImpl利用链 BasicDataSource利用链 Hashtable利用链 BadAttributeValueExpException利用链 HotSwappableTargetSource利用链 前文:【Web】浅聊Java反序列化之Rome——EqualsBean&ObjectBean-CSDN博客 前言 Rome中ToStringBean的利用…

186基于matlab的信号盲源分离算法

基于matlab的信号盲源分离算法,包括变步长盲源分离(EASI),RLS(自然梯度和普通梯度),并将三种方法分离结果进行对比。程序已调通,可直接运行。 186 信号盲源分离算法 变步长盲源分离 (xiaohongshu.com)

结合大象机器人六轴协作机械臂myCobot 280 ,解决特定的自动化任务和挑战!(下)

Limo Pro 小车建图导航 引言 前景提要:我们在上文介绍了使用LIMO cobot 实现一个能够执行复杂任务的复合机器人系统的应用场景的项目,从以下三个方面:概念设计、系统架构以及关键组件。 本文主要深入项目内核的主要部分,同样也主要…

使用R语言进行聚类分析

一、样本数据描述 城镇居民人均消费支出水平包括食品、衣着、居住、生活用品及服务、通信、文教娱乐、医疗保健和其他用品及服务支出这八项指标来描述。表中列出了2016年我国分地区的城镇居民的人均消费支出的原始数据,数据来源于2017年的《中国统计年鉴》&#xf…

简单多状态dp问题----删除并获得点数

740. 删除并获得点数 - 力扣(LeetCode) 本题就是表示不能选值相邻的两个数。 假设nums [ 1,2,3,4,5,6],那么这其实就类似一个打家劫舍问题: 即选1,就不能选2,只能选3,4,5&#xff…

excel常用操作备忘

目录 快捷键基础数据透视图统计某列的值出现的频数 数据有效性数据分列运算符顺序文本匹配中的通配符错误的类型(常与IF嵌套使用)函数RANK(num, ref, [order])MID(str, start, len)逻辑函数混合函数选取整列AVERAGEIF(range, criteria, average_range)TR…

Flink 学习3 - 流处理API的基本转换算子 + 多流转换算子

流处理API-Transform 1、基本转换算子 map、flatMap、filter通常被统一称为基本转换算子(简单转换算子) DataStream 里没有 reduce 和 sum 这类聚合操作的方法,因为 Flink 设计中,所有数据必须先分组才能做聚合操作。 先 keyB…

ASUS华硕天选2锐龙版笔记本电脑FA506ICB/FA706IC原装出厂Windows11系统,预装OEM系统恢复安装开箱状态

链接:https://pan.baidu.com/s/122iHHEOtNUu4azhVPnxNuA?pwdsqk7 提取码:sqk7 适用型号: FA506IM、FA506IE、FA506IC、FA506IHR FA506IR、FA506IHRB、FA506ICB、FA506IEB FA706IM、FA706IE、FA706IC、FA706IHR FA706IR、FA706IHRB、F…

《Effective Modern C++》- 极精简版 15-21条

本文章属于专栏《业界Cpp进阶建议整理》 继续上篇《Effective Modern C》- 极精简版 5-14条。本文列出《Effective Modern C》的15-21条的个人理解的极精简版本。 Item15、尽量使用constexpr constexpr形容对象 constexpr对象都是const,但是const对象不一定是conste…

单数码管(arduino)

1.连接方法 挨个点亮每个灯 #include <Arduino.h>int pin_list[] {4, 5, 19, 21, 22, 2, 15, 18}; int num_pins sizeof(pin_list) / sizeof(pin_list[0]); // 计算数组中的元素数量void setup() {// 设置每个引脚为输出for(int i 0; i < num_pins; i) {pinMode(p…

ArcGIS学习(十三)多源数据下的城市街道功能评估

ArcGIS学习(十三)多源数据下的城市街道功能评估 本任务带来的内容是多元数据下的城市街道功能评估。本任务包括两个关卡: 城市街道空间中观解读 城市街道功能详细评价 首先,我们来看看本任务的分析思路。 1.城市街道空间中观解读 下面我们正式进入第一关的内容一- 城市…

html--心花怒放

代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>Canvas 绘制一个❤</title><link rel"shortcut icon" href"../../assets/images/icon/favicon.ico" type"ima…

c#触发事件

Demo1 触发事件 <Window x:Class"WPFExample.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"Title"WPF Example" Height"600" Wi…

混合输入矩阵乘法的性能优化

作者 | Manish Gupta OneFlow编译 翻译&#xff5c;宛子琳、杨婷 AI驱动的技术正逐渐融入人们日常生活的各个角落&#xff0c;有望提高人们获取知识的能力&#xff0c;并提升整体生产效率。语言大模型&#xff08;LLM&#xff09;正是这些应用的核心。LLM对内存的需求很高&…

外包干了30天,技术明显退步。。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 这次来聊一个大家可能也比较关心的问题&#xff0c;那就是就业城市选择的问题。而谈到这个问题&a…

在Mac上安装nginx+rtmp 本地服务器

需要使用终端命令&#xff0c;如果没有Homebrew&#xff0c;要安装Homebrew,执行&#xff1a; ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 一、安装Nginx 1、先clone Nginx项目到本地&#xff1a; brew tap de…

redis缓存满了的话会发生什么?

线上问题 未及时加监控&#xff0c;导致线上redis被逐出&#xff0c;业务有损 示例&#xff1a; 一个key临时存储在redis等缓存中&#xff0c;如果该key在一段时间内有很大作用 比如一次业务请求&#xff0c;上游服务写入一个value&#xff0c;时长1小时&#xff0c;下游服务…

LiveNVR监控流媒体Onvif/RTSP功能-视频广场点击在线或离线时展示状态记录快速查看通道离线原因

LiveNVR视频广场点击在线或离线时展示状态记录快速查看通道离线原因 1、状态记录1.1、点击在线查看1.2、点击离线查看 2、RTSP/HLS/FLV/RTMP拉流Onvif流媒体服务 1、状态记录 1.1、点击在线查看 可以点击视频广场页面中&#xff0c; 在线 两个字查看状态记录 1.2、点击离线查…