手写简易操作系统(三)--加载Loader

前情提要

上一节我们讲了如何启动计算机,这一节我们讲如何加载内核,内核是存在于硬盘上的一段程序,要加载这段程序,那么必然需要从硬盘上读取数据,这里我们就需要使用 ATA PIO 模式

根据ATA规范,所有符合ATA的驱动器必须始终支持PIO模式作为默认的数据传输机制。

现在较为流行的SATA硬盘也是一种符合ATA标准的硬盘,所以当然也需要支持 ATA PIO,而 ATA PIO 较为简单,所以我们就将其当做默认的读取硬盘的模式

在实际应用中,为了获得更好的性能和效率,通常会选择更高级的硬盘访问模式,如 DMA 或 Ultra DMA,以及操作系统提供的直接访问硬盘的接口(如 Windows 的AHCI模式)。这些模式能够更有效地利用系统资源,提供更快速的数据传输速度。甚至是NVME,直接走PCIE通道与CPU直连。但是这些比较复杂,不在本文的考虑范围内。

一、硬盘的主要端口

image-20240309213607741

其中Primary为主通道,Secondary为从通道

其中主通道读时

  • 0x1F0 是数据端口
  • 0x1F1 是错误端口,可以返回错误信息,每一位都是一个错误信息,包括(0、AMNF未找到地址标记。1、TKZNF未找到零磁道。2、ABRT中止命令。3、MCR变更请求。4、IDNF未找到ID。5、MC 发生了变化。6、UNC不可纠正的数据错误。7、BBK检测到坏块。)
  • 0x1F2 是扇区数量端口
  • 0x1F3 是LBA低地址
  • 0x1F4 是LBA中地址
  • 0x1F5 是LBA高地址
  • 0x1F6 0-3位,在CHS寻址中表示柱头位,在LBA寻址中,表示LBA地址的24-27位。4位DRV,表示选择主盘或者从盘。5位、永远为1。6位、如果为0则为CHS寻址,如果为1则为LBA寻址。7位、永远为1。
  • 0x1F7 是状态寄存器端口 ,0位ERR,如果为1则表示出错了。3位Data ,如果为1表示硬盘已经把数据准备好了。6位DRDY,表示硬盘检测正常,可以执行命令。7位BSY,如果为1表示硬盘正繁忙,此寄存器中的其他位都无效。

主通道写时有一些yu寄存器有了不同的用途

  • 0x1F1 是参数端口,用于传递写硬盘时的参数
  • 0x1F7 是指令端口,我们主要用到了这么几个指令。0xEC,硬盘识别。0x20,读扇区。0x30,写扇区。

二、加载Loader

哈哈哈哈,上面说的是加载内核,现在又成了加载loader,没办法,加载内核之前就得加载Loader,Loader的作用有

  1. 加载内核:loader 负责将操作系统内核从存储设备(如硬盘、闪存)中读取到内存中,以便后续执行。
  2. 确认内核完整性:loader 在加载内核之前通常会对内核进行校验,以确保内核文件的完整性和正确性,避免因为损坏或错误的内核文件导致系统启动失败。
  3. 设置环境:loader 在加载内核前会设置好适当的执行环境,包括初始化硬件设备、建立内存映射关系等,为内核的正常执行做好准备工作。
  4. 启动内核:加载完内核后,loader 会将控制权转交给内核的起始地址,启动内核的执行,让操作系统开始运行。

由于MBR是占据了硬盘的第0扇区(以逻辑LBA方式,扇区从0开始编号,若是以物理CHS方式,扇区则从1开始编号),所以我们的loader就放在第1扇区,可以看第二章的内存布局,现在有两块内存可用,0x500~0x7BFF0x7E00~9FBFF,那我们就放在 0x600 的地方吧。下面我们接着改MBR

2.1、修改Mbr使其可以加载Loader

这里我们添加一点宏定义

; os/src/boot/boot.inc
LOADER_BASE_ADDR equ 0x600
LOADER_START_SECTOR equ 0x1

然后改写mbr

; os/src/boot/mbr.s
; 设置开始的地址,并且初始化寄存器
%include "boot.inc" 
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	; 11100001b 即背景色为黑,字体为白,不闪烁 mov byte [gs:0x02],'B'  ;mov byte [gs:0x03],0x0F	; mov byte [gs:0x04],'R'  ;mov byte [gs:0x05],0x0F	;mov eax,LOADER_START_SECTOR	 ; Loader起始扇区 mov bx, LOADER_BASE_ADDR     ; Loader起始内存地址mov cx, 1			         ; 待写入扇区数call rd_disk_m_16		     ; 执行读取硬盘程序jmp LOADER_BASE_ADDR         ; 跳转到Loader执行rd_disk_m_16:	   ; eax=LBA扇区号; ebx=Loader内存; ecx=扇区数量mov esi,eax	       ; 备份eaxmov di,cx		   ; 备份cxmov dx,0x1f2       ; 设置要写入端口,即读取端口数mov al,cl          ; 设置要读取扇区数out dx,al          ; 设置mov eax,esi	       ; 恢复eaxmov dx,0x1f3       ; 设置要写入端口,即LBA低地址              out dx,al          mov cl,8           ; ax右移八位   shr eax,clmov dx,0x1f4       ; 设置要写入端口,即LBA中地址 out dx,alshr eax,cl         ; ax右移八位   mov dx,0x1f5       ; 设置要写入端口,即LBA高地址 out dx,alshr eax,cl         ; ax右移八位and al,0x0f	       ; 保留低4位,设置高4位为 0000or al,0xe0	       ; 保留低4位,设置高4位为 1110mov dx,0x1f6out dx,almov dx,0x1f7       ;mov al,0x20        ; 读扇区指令               out dx,al.not_ready:            ; 未准备好nop                ; 不执行任何指令,占用一个机器周期in al,dx           ; 查看读取状态and al,0x88        ; 与 10001000 做与运算cmp al,0x08        ; 比较第三位和第七位jnz .not_readymov ax, di         ; 要读的扇区数mov dx, 256        ; 乘以256,即要读多少次mul dxmov cx, ax	       ; 将要读的次数传给cxmov dx, 0x1f0      ; 要读的端口号.go_on_read:in ax,dx           ; 向ax中读,一次读两个字节mov [bx],ax        ; 将ax中数据给bx地址的内存add bx,2		   ; bx中内存地址加2loop .go_on_read   ; 循环cx次ret; 将510个字节中剩余的空间填充为0
; $ 是当前地址
; $$ 是本节开头地址,也就是0x7c00
times 510-($-$$) db 0
db 0x55,0xaa

2.2、写一个小Loader

; os/src/boot/loader.s
%include "boot.inc" 
section loader vstart=LOADER_BASE_ADDR 
.begin_loader:mov byte [gs:0x00],'L'  ; 字符为M的ascii值mov byte [gs:0x01],0x0F	; 11100001b 即背景色为黑,字体为白,不闪烁 mov byte [gs:0x02],'O'  ;mov byte [gs:0x03],0x0F	; mov byte [gs:0x04],'A'  ;mov byte [gs:0x05],0x0F	;mov byte [gs:0x06],'D'  ;mov byte [gs:0x07],0x0F	;mov byte [gs:0x08],'E'  ;mov byte [gs:0x09],0x0F	;mov byte [gs:0x0A],'R'  ;mov byte [gs:0x0B],0x0F	;; 程序在此处卡住
jmp $

这里loader的作用还是输出一些内容作为指示

2.3、执行

执行前需要把脚本更新一下

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

执行!

image-20240309225254582

结束语

第三章也结束了,这一章我们讲了如何加载一个Loader,以及如何读写硬盘,下一章,我们就要开始讲一些有关于保护模式的东西了,先将这个Loader完善一下。

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

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

相关文章

深度学习的一些工具函数

文章目录 简介数据集划分数据集 简介 记录深度学习编写程序过程中的一些工具函数 数据集 划分数据集 数据集划分思路: 若数据集很小,直接随机打乱 import random random.shuffle(data)若数据集很大,选择随机打乱下标,根据下…

docker部署springboot jar包项目

docker部署springboot jar包项目 前提,服务器环境是docker环境,如果服务器没有安装docker,可以先安装docker环境。 各个环境安装docker: Ubuntu上安装Docker: ubuntu离线安装docker: CentOS7离线安装Docker&#xff1…

算法-排序

0、复杂度及稳定性 时间复杂度空间复杂度 稳定性(相等元素相对顺序不变) 冒泡排序 时间复杂度为O(n^2) 最坏/平均:O(n^2) 最好:O(n),序列有序 O(1)稳定插入排序 时间复杂度为O(n^2) 最坏/平均:O(n^2) 最好…

可视化场景(2):电商大屏-引爆业绩,直观呈现

hello,我是贝格前端工场,本期分享可视化大屏在电商领域的应用,如需要定制,可以与我们联络,开始了。 电商领域的可视化大屏可以提供实时的销售数据、用户行为分析、库存管理等信息,帮助企业实时监控经营状况…

java jdk17 HashMap解读

类描述 基于Hash表的Map接口实现。此实现提供了所有的可选的map操作,并且避免了null值和null键。(HashMap类大体上等价于Hashtable,除了它是非同步的和禁止null)。此类不保证map的顺序。特别是,不保证随着时间的变化顺序保持不变…

不知道吧,腾讯云轻量应用服务器使用有一些限制!

腾讯云轻量应用服务器相对于云服务器CVM是有一些限制的,比如轻量服务器不支持更换内网IP地址,不支持自定义私有网络VPC,内网连通性方面也有限制,轻量不支持CPU内存、带宽或系统盘单独升级,只能整个套餐整体升级&#x…

题目 2021: 坐标排序

题目描述: 请将坐标x,y,z依照以下规则排序: x为第一关键字,当x相同时,依照y(第二关键字)大小来排序,当y相同时,依照z大小来排序(第三关键字) 给出了若干坐标&#xff0c…

【AIGC调研系列】大模型的system prompt破解调研

大模型的system prompt破解方法实践主要涉及到prompt工程和提示注入等技术。首先,prompt工程是指通过精心设计prompt,以提高与大模型的交互效率和准确性。这包括了如何清晰地表达任务要求和期望结果[2],如何有效使用prompt[4],以及…

Anthropic 公司最新宣布,他们的 AI 聊天机器人模型击败了 OpenAI 的 GPT-4

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

Unity Text文本实现滚动跑马灯效果

在一些公告上我们经常会看到文字滚动跑马灯的效果。 那么在Unity上如何实现? 1、首先创建一个Text(或者TextMeshPro)组件,然后输入需要显示的文本内容,如图: 2、编写控制脚本TextRoll.cs: using System.Collections…

【MGR】MySQL Group Replication 监控

目录 17.4 Monitoring Group Replication 17.4.1 Group Replication Server States 17.4.2 The replication_group_members Table 17.4.3 The replication_group_member_stats Table 17.4 Monitoring Group Replication 17.4.1 Group Replication Server States 服务器实例…

钉钉h5应用 globalthis is not defined vite client

钉钉h5应用 globalthis is not defined vite client problem 背景 钉钉h5应用使用 vue3 vite 构建的前端工程 问题 h5页面在pc端浏览器和pc端钉钉打开正常h5页面在移动端钉钉打开异常 页面空白 通过调试工具找到报错信息 globalthis is not defined vite client reason …

ULTRAL SCALE FPGA TRANSCEIVER速率

CPLL支持2-6.25速率 QPLL支持速率 实际使用CPLL最高可以超过这个,QPLL最低也可以低于这个,xilinx留的阈量还是比较大。

数仓开发-2023/2/29

1.简单自我介绍 2.介绍下之前的公司离线数仓项目 3.sql和hivesql区别? 4.sql的执行顺序? 5.hive的优化 6.说下你之前公司来,你的技能层次在每个公司?你怎么评价你的技能? 7.你的之前业务主要是做什么?我说了…

谈一谈mysql的删除操作 DELETE、TRUNCATE和DROP

MySQL中的删除操作可以通过多种语句实现,包括DELETE、TRUNCATE和DROP。具体来看: DELETE: 属于数据库的DML(Data Manipulation Language)操作语言。 可以删除一行或多行数据,但不会删除表结构。 在InnoD…

这是谁的女儿?其母亲早已红过头了,现在小小年纪的她也爆红网络,没想到吧?

这是谁的女儿?其母亲早已红过头了,现在小小年纪的她也爆红网络,没想到吧? 原来,作母亲的她在红极一时后似乎沉寂了下来,没想到她11岁的女儿近年来也在社交媒体上走红,她为何也成了小网红呢&…

mock项目:

为什么不使用react严格模式 <React.StrictMode><App /></React.StrictMode>,使用严格模式有一些好处&#xff0c;它会执行额外的检查以帮助发现常见的问题&#xff0c;并提供更好的错误和警告信息。 第三方库的兼容性问题&#xff1a;有些第三方库可能不支持…

数字化转型导师坚鹏:大模型的应用实践(金融)

大模型的应用实践 ——开启人类AI新纪元 打造数字化转型新利器 课程背景&#xff1a; 很多企业和员工存在以下问题&#xff1a; 不清楚大模型对我们有什么影响&#xff1f; 不知道大模型的发展现状及作用&#xff1f; 不知道大模型的针对性应用案例&#xff1f; 课程…

C# 高级特性(十一):多线程之async,await

之前使用Thread和Task启动多线程时都会遇到一个麻烦&#xff0c;就是如何反馈结果。在代码里就是如何设计回调函数。如果带界面还得考虑UI线程的问题。 而使用async&#xff0c;await可以达到两个效果。 1 不用设计回调函数&#xff0c;直接按单线程的格式写。 2 不用考虑UI…

【决策树】预测用户用电量

决策树预测用户用电量 文章目录 决策树预测用户用电量  &#x1f449;引言&#x1f48e;一、 数据预处理数据预处理初步数据分析 二、 机器学习算法决策树回归预测用电量决策树模型介绍&#xff1a;回归预测 三、 可视化结果四、 数据分析与结论代码如下 &#x1f449;引言&a…