【自制操作系统】系统启动流程,工具使用和启动区的制作

📝本文介绍
本文主要从系统系统的启动流程开始,中间介绍一些所用工具的使用方法,最后将完成一个启动区的制作。此次的启动区只涉及到汇编代码。
👋作者简介:一个正在积极探索的本科生
📱联系方式:943641266(QQ)
🚪Github地址:https://github.com/sankexilianhua
🔑Gitee地址:https://gitee.com/Java_Ryson
由于本人的知识所限,如果文章有问题,欢迎大家联系并指出,博主会在第一时间修正。

文章目录

  • 📕系统的启动
    • 📖BIOS是什么
    • 📖如何启动
  • 📙部分基础知识和工具的使用
    • 📖各类重要寄存器
    • 📖nasm使用
    • 📖dd使用
    • 📖qemu简单使用
    • 📖Makefile编写
  • 📘启动区的制作
    • 📖完整代码
    • 📖ipl的解析
    • 📖boot_info解析
  • 📗实际效果

  开始之前,先跟大家说明:本文会涉及到较多地默认设置,也就是从最开始做计算机,做操作系统等等的前辈们留下来的。一些感到疑惑或者博主没有说清楚的地方可以搜索一下,说不定是固定设置或者遗留问题,也可以在评论区提问。

📕系统的启动

📖BIOS是什么

  BIOS是英文"Basic Input Output System"的缩略词,直译过来后中文名称就是"基本输入输出系统"。在IBM PC兼容系统上,是一种业界标准的固件接口。BIOS是个人电脑启动时加载的第一个软件。
  其实,它是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序,它可从CMOS中读写系统设置的具体信息。 其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。此外,BIOS还向作业系统提供一些系统参数。系统硬件的变化是由BIOS隐藏,程序使用BIOS功能而不是直接控制硬件。现代作业系统会忽略BIOS提供的抽象层并直接控制硬件组件。
  其实,计算机开始时,将执行的第一个程序,就可以认为是这个程序。(除了最开始的一个跳转指令)。

📖如何启动

  在讲述如何启动之前,或许需要先讲述我自己对于计算机硬件的理解:硬件是一台巨大的状态机。这里会涉及到一个状态机的概念。状态机实际上就是条件的改变可能会引起状态的改变。学过数逻应该会更加清楚一点。硬件实际上也差不多。根据pc寄存器的值,一条条从内存的地方取出指令,之后译码,去执行,根据所执行的指令,就会改变相应寄存器的状态(值),最终可以实现整个计算机像另一状态的变化。
  这个问题还会涉及到内存布局的问题,在实模式底下,到底内存如何分配呢?这里有篇博客,用来防止照片失效。

在这里插入图片描述
在实模式底下,我们能操作的内存只有1M(为什么大家可以自行搜索)。
  现在,我们正式开始介绍系统启动的4个跳跃。
  第一跳 :系统启动时会先跳转到0xFFFF0这个位置。这里是BIOS程序的入口。
  第二条我们可以发现,这个位置到0xFFFFF只剩下16字节的空间,大概率只能放得下一条指令,所以我们用来跳转,跳到一个更加大的空间,去执行我们需要的任务。这里跳转指令会跳转到0xfe05b。
  第三跳:这里就开始执行一些硬件自检等活动,完成后,**加载(从外存中复制到内存)启动区的程序到0x7c00(规定)**并跳转到该位置。
  第四跳:启动区的程序主要是加载操作系统内核,之后会跳转到内核存储处开始执行。
  更加详细的内容,大家也可以查看这篇博客

📙部分基础知识和工具的使用

📖各类重要寄存器

8位寄存器:

  • AL——累加寄存器低位(accumulator low)
  • CL——计数寄存器低位(counter low)
  • DL——数据寄存器低位(data low)
  • BL——基址寄存器低位(base low)
  • AH——累加寄存器高位(accumulator high)
  • CH——计数寄存器高位(counter high)
  • DH——数据寄存器高位(data high)

16位寄存器:

  • AX——accumulator,累加寄存器
  • CX——counter,计数寄存器
  • DX——data,数据寄存器
  • BX——base,基址寄存器
  • SP——stack pointer,栈指针寄存器
  • BP——base pointer,基址指针寄存器
  • SI——source index,源变址寄存器
  • DI——destination index,目的变址寄存器

32位寄存器是在16位寄存器前添加上e,如eax,ebx,ecx等.64位则变e为r,rax,rcx等。当然64位也有r0,r1,r2等等的写法,具体内容可自行了解。

📖nasm使用

nasm这里就只介绍最简单的用法目前来说足够本文使用。nasm主要是一些参数等的使用,用多了熟悉后会更加顺手。这就不是把一些参数贴上来能解决的。

nasm -o xxx.bin xxx.asm
或
nasm xxx.asm -o xxx.bin

这里的-o指的是将目标文件命名为什么。后面的asm文件就是我们所写的汇编文件。其余的一些参数可自行了解

📖dd使用

dd命令,可以往磁盘中写相应的数据。

dd if=? of=? seek=? bs=? count=?

if指向要输入的文件,of指向要输出的文件。(通俗就是把if的文件写入of)。seek是否要跳过前几个部分。如seek=1,就会跳过512个字节。bs用于指定块大小,默认情况下都为512字节。count指的是处理多少块数据。

📖qemu简单使用

  qemu的用法也很多,但我们这里主要用来模拟x86的64位系统就可以,当然其他系统可以启动应该也行。
  首先要介绍的是创建磁盘映像的功能。

qemu-img create -f xxx name(eg:os.raw) size
eg:qemu-img create -f raw os.raw 1440k

  接下来是使用我们制作好的磁盘映像来启动

qemu-system-x86_64 os.raw
qemu-system-x86_64 -derive file=? if=floppy

如果我们制作的是软盘映像,最好指明是floppy,否则读取磁盘时可能会出现问题(博主就因为这个问题困扰了很久)

📖Makefile编写

  这里涉及到另一个工具,make。 大家可以自行去网络上搜索下载一个,并如同之前一样,将其添加进环境变量。这样之后不论在哪个文件夹下都可以方便使用。这个工具是为了方便使用和规范化整理。
  使用这个工具涉及到了Makefile的书写,这里放上本文使用到的makefile,不够用正规,不过目前足够使用。

ipl.bin: ipl.asm nasm -o ipl.bin ipl.asm
boot_info.bin:boot_info.asmnasm -o boot_info.bin boot_info.asmos.raw:	ipl.bin boot_info.binqemu-img create -f raw os.raw 1440kdd if=ipl.bin of=os.raw bs=512 count=1 dd if=boot_info.bin of=os.raw seek=1 bs=512 count=31 seek=1 run:make -r os.rawmake cleanqemu-system-x86_64 -drive file=os.raw,if=floppy,index=0,media=disk,format=raw
clean:del ipl.bindel boot_info.bin

这样,我们在命令行时就无需每次都手打这些指令,直接make run就可以了,就会主动去执行这些指令。
  那么这个是怎么执行的呢?我们可以看到,run中首先要制作一个os.raw,但所以会去上面寻找os.raw的制作方法,需要什么?冒号后面可以看到,需要ipl.bin boot_info.bin,但目前没有,那就再找。找到这两个,分别需要其asm文件,这两个文件是我们一早就写好的,于是就开始制作两个bin,制作完成后,回来制作os.raw,先创建一个空映像,之后用dd将其写入。之后回来执行,clean,clean里主要是清除一些中间中间文件,让整个文件夹看起来清爽一些。由于是在window下,所以我们使用del命令。linux就使用rm。之后启动qemu就可以了。
  跟着这个不太规范的makefile写个一两次,大致理解之后就可以开始玩自己的makefile了。

📘启动区的制作

📖完整代码

  我们这里先放上一份完整的代码,再逐一去说明
ipl.asm:

;告诉BIOS把启动区加载到内存的该位置。ORG 0x7c00CYLS equ 10;调用BIOS 清屏mov ax,0x0600mov bx,0x700mov cx,0mov dx,0x184fint 0x10;清屏完后,输出os介绍信息
entry:;先设置各种寄存器xor ax, axmov ds, axmov es, axmov ss, ax               mov sp, 0x9000          mov si,msg
print_loop:mov al,[si]add si,1cmp al,0je read_diskmov ah,0x0emov bx,15int 0x10jmp print_loopread_disk:mov ax,0x0820mov es,axmov ch,0	;磁道号mov cl,2	;扇区号mov dh,0	;磁头号mov bx,0	;读入内存哪块区域,同时需要看es的值
read_disk_loop:mov si,0	;记录失败次数
retry:;设置入口参数mov ah,0x02 ;设置功能号,0x02标识读,03为写mov al,1	;读入扇区数mov dl,0	;驱动器号int 0x13	;调用磁盘BIOSJNC next	;,没出错,就接着读下一个;JC 	error	mov ah,0x00	;能到这里就说明一定有出错mov dl,0x00int 0x13	;重置驱动器inc sicmp si,5jbe retryjmp error;;出错超过5次就跳转到error
next:mov ax,esadd ax,0x0020 ; 512/16=32 这里寻址是[ES:BX] 所以原本512字节要除16mov es,axadd cl,1	cmp cl,18 	;一个道18个扇区jbe read_disk_loopmov cl,1	;重置扇区号add dh,1	;磁头号,两面cmp dh,2jb  read_disk_loopmov dh,0	;add ch,1cmp CH,CYLS ;总读取磁道数JB	read_disk_loopjmp 0x8200fin:hltjmp finerror:mov si,error_info
error_loop:mov al,[si]add si,1cmp al,0je finmov ah,0x0emov bx,15int 0x10jmp error_loopmsg:DB	0x0a			;换行DB	"hello-os"DB	0	 error_info:DB	0x0a			;换行DB	"read_disk_error"DB	0	 resb 510-($-$$);将剩下的空间用0填满DB 0x55,0xaa

boot_info.asm:

CYLS equ 0x0ff0
LEDS equ 0x0ff1
VMODE equ 0x0ff2
SCRNX equ 0x0ff4
SCRNY equ 0x0ff6
VRAM equ 0x0ff8org 0xc200 ; 这个程序将要被装载到内存的什么地方呢?	mov al,0x13 ; VGA显卡,320x200x8位彩色mov ah,0x00int 0x10mov byte[VMODE],8mov word[SCRNX],320mov word[SCRNY],200mov dword [VRAM],0x000a0000;用BOIS取得键盘上各种LED指示灯的状态mov ah,0x02int 0x16	;键盘BIOSmov [LEDS],al
fin:HLTJMP fin

📖ipl的解析

  看完完整代码之后,我们再来逐一分析。

	ORG 0x7c00CYLS equ 10

ORG是Origin的缩写:起始地址,源。在汇编语言源程序的开始通常都用一条ORG伪指令来实现规定程序的起始地址。如果不用ORG规定则汇编得到的目标程序将从0000H开始。也就是cs:0处。
第二条的CYLS实际上就只是一个常量的定义,equ实际上就是equal,也就是我们把CYLS定义为10这个数。

;调用BIOS 清屏mov ax,0x0600mov bx,0x700mov cx,0mov dx,0x184fint 0x10

这里和底下的一些具有int的代码片段都大致相同,根据调用BIOS程序的规定,设置好指定的寄存器值后,调用BIOS中断。int就是interrupt。

	;先设置各种寄存器xor ax, axmov ds, axmov es, axmov ss, ax               mov sp, 0x9000          

这一段,实际上就是在初始化一些寄存器。xor异或,同一个数异或实际上就相当于清零。所以也有使用mov ax,0的写法。mov指令这个就相当于copy吧,或者用c语言的=来理解也可以,因为mov后原寄存器的值不会变化。

	mov si,msg
print_loop:mov al,[si]add si,1cmp al,0je read_diskmov ah,0x0emov bx,15int 0x10jmp print_loopmsg:DB	0x0a			;换行DB	"hello-os"DB	0	 

  这一段就是输出一个字符串了。这里我们把msg拿上来一起看。db就是define byte,dw是define word。而dd 是define double word。使用DB作为数据类型的时候,字符串长度不受限制默认字符串的每一个字符占一个字节,并且存储过程中,是按照一个字符占一个字节的方式,顺序依次存储的。这里讲msg赋值给si,那么si指向的就是该字符串的首地址。之后一个一个输出就可以了。同样的,设置好寄存器后,调用BIOS10号中断程序来处理。
  这里还有另一种方法,就是直接往显存中写数据。可以查看这篇博客,这里不再赘述。

read_disk:mov ax,0x0820mov es,axmov ch,0	;磁道号mov cl,2	;扇区号mov dh,0	;磁头号mov bx,0	;读入内存哪块区域,同时需要看es的值
read_disk_loop:mov si,0	;记录失败次数
retry:;设置入口参数mov ah,0x02 ;设置功能号,0x02标识读,03为写mov al,1	;读入扇区数mov dl,0	;驱动器号int 0x13	;调用磁盘BIOSJNC next	;,没出错,就接着读下一个;JC 	error	mov ah,0x00	;能到这里就说明一定有出错mov dl,0x00int 0x13	;重置驱动器inc sicmp si,5jbe retryjmp error;;出错超过5次就跳转到error
next:mov ax,esadd ax,0x0020 ; 512/16=32 这里寻址是[ES:BX] 所以原本512字节要除16mov es,axadd cl,1	cmp cl,18 	;一个道18个扇区jbe read_disk_loopmov cl,1	;重置扇区号add dh,1	;磁头号,两面cmp dh,2jb  read_disk_loopmov dh,0	;add ch,1cmp CH,CYLS ;总读取磁道数JB	read_disk_loopjmp 0x8200

  好了,到了启动区最重要的功能,读磁盘内容了。读磁盘有两种方式,一种是chs的方法,一种是使用lba地址的方法,两种方法需要设置的寄存器值有一些差别,大家要注意看其对应的要求。chs就是我们使用的物理结构,柱面,磁头,扇区。而lba就不管这个了,把磁盘看成一个大的空间,分成512个字节一小部分,计算时就是(柱面号*磁头数+磁头号)*扇区数+扇区编号-1。
  当然,读磁盘有可能出现各种问题导致某一次失败,所以我们需要让其有重来的机会。我们这里将其设定为5次,5次及之前,出现错误都会重置后跳转到retry继续读取,如果超过五次,就会跳转到error,打印read_disk_error。而next之后实际上就是要继续读取的写法了,1440kb的软盘结构:2面、80道/面、18扇区/道、512字节/扇区。所以才会有后面的那些判断。
  还有一个小问题,就是防止的地方,由于一次读进来一个扇区,512字节,所以每次之后都需要把内存防止位置在加上512字节,由于我们在es上操作,es实际计算地址时是[ES:BX],es需要左移4位也就是×16。(为什么,就是intel的遗留问题了,有兴趣可以搜索看看,没兴趣就算了。)所以512÷16=32,化为16进制就是0x20,所以才会每次给es加上0x20。但es又不能直接进行加减运算,所以只好先拿出来给ax,做完运算再放回去。

fin:hltjmp fin

这里就是停止,hlt会让cpu停止,等待下一个操作,而不是一直运行着,浪费资源。

📖boot_info解析

	org 0xc200 ; 这个程序将要被装载到内存的什么地方呢?	mov al,0x13 ; VGA显卡,320x200x8位彩色mov ah,0x00int 0x10mov byte[VMODE],8mov word[SCRNX],320mov word[SCRNY],200mov dword [VRAM],0x000a0000

  部分注释已经在上面,里面的一些参数依照如下来设置的:

设置显卡模式(video mode)
AH=0x00;
AL=模式:(省略了一些不重要的画面模式)
0x03:16色字符模式,80 × 25
0x12:VGA 图形模式,640 × 480 × 4位彩色模式,独特的4面存
储模式
0x13:VGA 图形模式,320 × 200 × 8位彩色模式,调色板模式
0x6a:扩展VGA 图形模式,800 × 600 × 4位彩色模式,独特的4
面存储模式(有的显卡不支持这个模式)
返回值:无

所以这实际上也只是一个设置好寄存器调用的问题。

📗实际效果

这里还没有把boot_info写入到磁盘,所以虽然跳转了,但是没有发生什么。主要看一下没有调用画面前的状态。
在这里插入图片描述

调用后,光标应是消失状态。
在这里插入图片描述

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

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

相关文章

【Week Y1】调用官方权重进行检测

YOLO白皮书之调用官方权重进行检测 一、下载yolo-v5s源码,并配置编译环境二、输入本地图片查看检测结果三、输入本地视频查看检测结果 🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项…

【大厂AI课学习笔记NO.71】AI算力芯片GPU/TPU等

AI算力芯片的发展历程 人工智能(AI)算力芯片的发展历程紧密地跟随着AI技术的发展脚步。从早期的基于传统中央处理器(CPU)的计算,到图形处理器(GPU)的广泛应用,再到专门为AI设计的处…

外包干了6天后悔了,技术明显进步。。。。。

先说一下自己的情况,本科生,19年通过校招进入广州某软件公司,干了接近3年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

【Kafka系列 08】生产者消息分区机制详解

一、前言 我们在使用 Apache Kafka 生产和消费消息的时候,肯定是希望能够将数据均匀地分配到所有服务器上。 比如很多公司使用 Kafka 收集应用服务器的日志数据,这种数据都是很多的,特别是对于那种大批量机器组成的集群环境,每分…

YOLOv5-Openvino-ByteTrack【CPU】

纯检测如下: YOLOv5-Openvino和ONNXRuntime推理【CPU】 YOLOv6-Openvino和ONNXRuntime推理【CPU】 YOLOv8-Openvino和ONNXRuntime推理【CPU】 YOLOv9-Openvino和ONNXRuntime推理【CPU】 注:YOLOv5和YOLOv6代码内容基本一致! 全部代码Github&…

P8680 [蓝桥杯 2019 省 B] 特别数的和:做题笔记

目录 思路 代码 题目链接: P8680 [蓝桥杯 2019 省 B] 特别数的和 思路 最开始我思路主要是从数字转字符串上想的。因为我们需要判断每一位是否是特殊数,字符串很容易做到这一点,只是在数字相加这一步不好实现。 需要用到字符串与数字的…

实验二(二)OSPF路由协议基础实验

1.实验介绍 1.1关于本实验 开放式最短路径优先 OSPF(Open Shortest Path First)是IETF 组织开发的一个基于链路状态的内部网关协议(Interior Gateway Protocol)。目前针对 IPv4 协议使用的是 OSPF Version 2(RFC2328);OSPF 作为基于链路状态的协议,OSPF 具有以下优…

乡村治理深度解析:策略、挑战与解决方案

毋庸置疑,在今天这个崭新的时代,乡村治理的过程已然向我们发出了挑战。为了迎难而上,我们必须摒弃陈旧观念,勇敢迎接并大胆尝试探索与实践新的思路!为了达到这一宏伟目标,我们需要首先廓清如下关键概念&…

Qt教程 — 1.1 Linux下安装Qt

目录 1 下载Qt 1.1 官方下载 1.2 百度网盘下载 1.3 Linux虚拟机终端下载 2 Qt安装 3 安装相关依赖 4 测试安装 1 下载Qt 1.1 官方下载 通过官网下载对应版本,本文选择的版本为qt-opensource-linux-x64-5.12.12,Qt官方下载链接:htt…

L1-7 分寝室(Python)

学校新建了宿舍楼,共有 n 间寝室。等待分配的学生中,有女生 n0​ 位、男生 n1​ 位。所有待分配的学生都必须分到一间寝室。所有的寝室都要分出去,最后不能有寝室留空。 现请你写程序完成寝室的自动分配。分配规则如下: 男女生不…

diffusion model(十二): StableCascade技术小结

infopaperhttps://arxiv.org/abs/2306.00637githubhttps://github.com/Stability-AI/StableCascade/tree/master个人blog位置http://myhz0606.com/article/stablecascadehttp://stability.AI bloghttps://stability.ai/news/introducing-stable-cascade 前置知识: …

window mysql 安装出现的问题

1.安装到最后时,报错:authentication_string doesnt have a default value 解决办法: 1.不要关掉该页面,点击skip。 然后单击 back 回退到如下界面 2.去掉 Enable Strict Mode。 不要勾选 2. 最后一步:Start Servic…