学习计算机启动过程的前置知识是什么呢?(二)

本讲只是为了澄清以下问题:

当我们按下电源按钮时究竟会发生什么?

好吧,这似乎是很多人都想了解的问题,有时也很疑惑,为什么看似简单的问题却找不到答案?

问得好,我不知道为什么会这样,但我猜是因为:

我认为当你搜索这个问题的答案时,你发现的大部分内容都是这样的描述:

BIOS 将控制权转移到“引导顺序”中的第一个存储设备:硬盘。然后在硬盘中寻找主引导记录分区,这个分区告诉电脑操作系统在哪里,操作系统被加载到内存中,然后就可以看到经典的启动界面,启动过程就完成了.

这个描述太神奇了,为什么BIOS会主宰这个?你如何根据引导顺序调用它?为什么这个分区被加载到内存中,为什么它告诉计算机操作系统在哪里?受不了这么魔性的描述,必须说清楚。

首先,要学点东西,必须有一个先决知识,我们把它当成已知的,我不能从分子的原子组成来解释其原理。学习计算机启动过程的必备知识是什么?我要求您了解以下内容:

内存是存储数据的地方。给定一个地址信号,内存可以返回该地址对应的数据。

CPU的工作方式是不断从内存中取出指令并执行。

CPU从内存中的哪个地址取指令是由寄存器中的值决定的,它会不断地执行+1操作,或者跳转指令指定它的值是什么。

好了,你只需要知道这三个前提,就可以专业讲解你电脑的启动过程了。

一、为什么 BIOS 占主导地位?

据说开机后BIOS开始运行自己的程序,进行硬件自检,加载引导区。我不服气,为什么开机后BIOS里的程序会执行?为什么不在记忆中?为什么不在硬盘上?

好吧,不要怀疑前置知识,CPU的工作方式是不断从内存中取出指令并执行,那为什么说在BIOS中执行程序呢?这就不得不说内存映射了。

二、内存映射

CPU 地址总线的宽度决定了可访问内存空间的大小。例如16位CPU地址总线宽度为20位,地址范围为1M。 32位CPU地址总线宽度为32位,地址范围为4G。您可以计算出我们目前 64 位机器的地址范围。

但是,可访问的内存空间这么大,并不代表全部被内存使用,也就是说,寻址的对象不仅仅是内存,还有一些外设也是通过地址总线访问的,所以为什么?访问这些外围设备?就是在地址范围内画一块区域,这块用来做显存,那块用来做硬盘控制器,以此类推。

其实不符合我们的前置知识,所以可能有一个错误的理解方式,即内存中的这个位置是显存,那个位置是硬盘控制器。当我们在对应位置进行读写时,就相当于在显存等外设的对应位置进行读写,就好像这些外设的存储区域映射到内存中的某个区域一样。这样我们就不用担心外设了,重点还是放在了简单的内存上。这称为内存映射。

太好了,现在有了简单的前置知识就可以理解了,让我们继续吧。

三、实模式下的内存分布

刚才提到内存是为各个外设划分区域的,那么问题自然就来了,哪个区域分配给哪个外设呢?如果是规则,最好有一张桌子。嗯,是的,确实有。它是实模式下的内存分配。作者为它画了一张图:

在此处插入图片说明

哦,我真是个小天使。我已经展示了比例。如果你能找到比我更直观的东西,请给我留言。稍后将解释实模式。现在简单的理解就是电脑刚开机时只有1M内存可用。

我们看到内存被各种外设分割,也就是映射到内存中。 BIOS比较狠,不仅它的空间映射到内存位置0xC0000 – 0xFFFFF,而且里面的程序在开头也占用了一些区域磁盘初始化是什么意思,比如在内存开头写中断向量表,真是称为先到先得。

四、怎么从BIOS里的程序开始执行

好的,现在我们知道BIOS中的信息映射到内存位置0xC0000 – 0xFFFFF,而最关键的系统BIOS映射到位置0xF0000 – 0xFFFFF。如果我现在说,当 CPU 开启时,它会执行这个区域的代码,然后在一次操作后启动。你肯定想喷我。

这自然有一个猜想。我们需要用到另外一个前置知识,即CPU从内存中取出并执行到哪里去执行呢?是 PC 寄存器中的地址值。 BIOS程序的入口地址,也就是起始地址,是0xFFFF0(人家是这么写的),也就是电源键一按,就必须有神通改变pc里面的值寄存器到 0xFFFF0,然后 CPU 开始不停地运行。跑了。是的,下一句可能就是你找了很久的答案,请做好准备:

在你开机的那一刻,CPU的PC寄存器被强制初始化为0xFFFF0。具体来说,CPU将段基地址寄存器cs初始化为0xF000,将偏移地址寄存器IP初始化为0xFFF0。根据实模式最终地址计算规则,段基地址左移4位,加上偏移地址。 ,得到最终的物理地址,即抽象出来的PC寄存器地址为0xFFFF0。

在学习这方面的知识的时候,看到这句话解决了我心中许久的疑惑。多么简单粗暴的事实。写到这里,我也松了一口气,因为剩下的过程几乎就像流水账一样。

至于如何强制初始化,我觉得已经越过了前置知识的界限。此外,各个厂商的硬件实现也不一定相同。方法有很多,而且非常简单。讨论没有多大意义。

五、BIOS里面写了什么程序?

好的,我们现在知道BIOS映射到内存中的某个位置,CPU在启动的那一刻强制将自己的pc寄存器初始化为BIOS程序的入口地址。从这里开始,CPU 不停地运行。 那么接下来的问题似乎就很自然的被问到了,就是BIOS程序里面写了什么?

在 BIOS 程序中发布所有二进制信息是不合适的。让我们分析一些主要的。我们先猜猜,你看到入口地址是0xFFFF0,说明程序是从这里开始执行的。实模式下内存的下边界为0xFFFFF,即只剩下16个字节的空间来写代码。这还算什么?如果你有心,应该能猜到入口地址可能是跳转指令,跳转到更大的空间执行自己的任务。没错,存储在0xFFFF0的机器指令,翻译成汇编语言是:

jmp far f000:e05b

表示跳转到物理地址0xfe05b开始执行(回想一下前面提到的实模式地址计算方法)。

从地址 0xfe05b 开始,是 BIOS 真正工作的代码。这段代码会检测一些外设信息,初始化硬件,创建中断向量表并填写中断程序。这里就不展开部分了,这只是一个硬编码的程序,对理解引导过程没有帮助。后面我们看精彩的部分,也就是 BIOS 的最后一项工作:加载引导区。

六、什么是0x7c00

真实的地方就是真实的,我永远不会让加载的魔法词出现在这里,让我们现在把它分解成人类的话。

其实这个词并不神奇。加载在计算机领域是指将设备(如硬盘)上的程序复制到内存中的过程。加载引导区的过程翻译为 BIOS 程序将引导区的内容复制到内存中的某个区域。那么问题自然就来了,创业区在哪里?它在内存中复制到哪里?然后?让我们一一解答。

什么是发射区?就算不知道,也应该能猜到一定是一个符合一定特点的区域,所以人们称之为创业区。应该满足什么特点?别着急,不知道各位有没有设置BIOS启动顺序的经验。通常有U盘启动、硬盘启动、软盘启动、CD启动等,BIOS会依次读取这些启动盘0、磁道0、1扇区内容。

至于磁盘格式的划分,本文不再赘述。简而言之,对于内存来说,我们可以通过给出一个数字地址来获取这个地址的数据,而对于磁盘来说,我们需要给出磁头、柱面、风扇这三个信息才能定位到某个位置的数据,这只是描述位置的一种方式。

继续说,0盘的0磁道1扇区的内容一共512字节。如果最后两个字节分别是 0x55 和 0xaa,那么 BIOS 会将其视为引导区。如果没有,则继续下一个设备,依次查找扇区0、磁道0、扇区1的内容。如果最终没有找到符合条件的,则直接报没有引导区的错误。

BIOS 找到这个引导区域时会做什么?哦,前面说了,就是加载,也就是把这512个字节的内容复制到内存中的0x7c00这个位置。如何复制?当然是命令。有什么指示?这里只能简单的说指令集中有in和out,分别是用来将外设中的数据复制到内存中,或者将内存中的数据复制到外设中,使用这两条指令和外设为我们提供的阅读方法可以做到这一点。

引导区的内容已经被BIOS程序复制到内存中0x7c00的位置了,然后呢?这其实不难猜。 boot区的内容就是我们自己写的代码。复制到这里之后,就开始执行了。之后,我们的程序接管下一个进程,BIOS的任务就结束了。所以复制后,下一步应该是跳转指令!没错,就是这样PC寄存器变成0x7c00,指令从这里开始执行。

嗯?不知道大家有没有注意到,我们好像又把之前的魔法语言翻译成了中文了,我们开头说:

BIOS 将控制权转移到第一个存储设备。

那么这句话是什么意思呢?即BIOS将引导区的512字节复制到内存的0x7c00位置,并使用跳转指令将pc寄存器的值指向0x7c00。你看,这不是几句话,所以让我们把这个问题简单明了。

哦对了,现在好像只剩下一个问题了,为什么一定是0x7c00?好问题,当然答案也很简单,就是别人的BIOS开发团队是这样设置的,以后也不好改,不然不兼容。为什么不改变呢?我们来看一个简单的 512 字节的启动代码。 (代码摘自《30天自制操作系统》)

;你好操作系统

;TAB=4

ORG 0x7c00 ;程序在0x7c00处加载到内存中

;程序主体

条目:

MOV AX,0 ;初始化寄存器

MOV SS,AX

MOV SP,0x7c00

MOV DS,AX ;将段寄存器初始化为0

MOV ES,AX

MOV SI,msg

输入循环:

移动 AL,[SI]

添加 SI,1

CMP AL,0 ;遇到以0结尾的则跳出循环,不打印新字符

JE 鳍

MOV AH,0x0e ;指定文字

MOV BX,15 ;指定颜色

INT 0x10 ;调用BIOS显示字符函数

JMP 循环

鳍:

HLT

JMP 鳍

味精:

数据库 0x0a,0x0a ;换行,换行

数据库“hello-os”

数据库 0x0a ;换行

DB 0 ;0 结束

RESB 0x7dfe-$;填充 0 到 512 个字节

DB 0x55, 0xaa ;可启动设备标识符

我们看第一行:

ORG 0x7c00

这个数字就是刚才提到的引导区的加载位置。这行汇编代码只是意味着将 0x7c00 添加到以下地址。因为BIOS在这里加载引导区的代码,是有偏移量的,所以凡是写引导区的代码的,一开始都需要写这样的代码,否则所有的位都会被序列化。

因为都是写操作系统的人,boot区的第一行汇编代码有这个数字写死了,所以BIOS开发者原来设置的数字不好改,不然得联系每个操作系统都一一公司的开发者说:“哦,让我把这个地址改一下,你就可以改了。”推动另一个团队修改公司的代码需要大量的工作,想想推动需要多少劳动力。而且,就算改了,以前的代码也不兼容,不应该被人骂死。

最后一行:

数据库 0x55, 0xaa

这也验证了我们之前说的512字节的最后两个字节是0x55 0xaa,BIOS会认为是引导区,会加载,仅此而已。

回头看0x7c00的值,其实是个死值,不过还是有人问,一定有它的合理性。其实我的解释只能说这个值是别人规定的,后面的人给他们解释其中的合理性。这并不意味着人们一开始就必须这样想,就像我们做中文阅读理解题一样。

第一个 BIOS 开发团队是 IBM PC 5150 BIOS,当时被认为是第一个操作系统的是 DOS 1.0 操作系统,BIOS 团队假设它是用于的。但操作系统尚未推出,BIOS 团队假设其操作系统的最低内存要求为 32 KB。 BIOS希望自己加载的boot区的代码尽量往前走,这样更“安全”,不会过早被其他程序覆盖。但是如果只剩下512字节,感觉太悬空了,还有一些栈空间要预留,那就扩容到1KB吧。所以 32 KB 的结尾是 0x8000,减去 1KB(0x400) ,正好是 0x7c00。哇,太精确了,可以解释一下。

七、启动区的代码写了什么

其实到这里,我的文章应该就戛然而止了磁盘初始化是什么意思,因为原来的问题已经解决了,CPU已经从我们预期的位置开始马不停蹄的跑了,万事开头难,而且剩下的内容,也就是操作系统想怎么玩就怎么玩。

但我觉得不够有品位,而且似乎还有一些问题在你的脑海中挥之不去。比如这个问题:

启动区的代码写了什么? 512字节就是所有操作系统的内容?

这个问题问得好,512字节真的做不了什么,现在的操作系统怎么非得以M为单位,512字节还远远不够,这是怎么回事?

其实按照前面的思路我们可以猜到,BIOS用很少的代码就将512字节引导区的内容加载到内存中,然后跳转开始执行。按照这个套路,512字节的启动区码是不是也可以把更多的磁盘中存储的操作系统程序加载到内存中的某个位置,然后跳转到那里?

是的,就是这样。所以BIOS负责加载引导区,而引导区负责加载真正的操作系统内核,对吧?

因为用于启动盘的磁盘是写操作系统的厂家制作的,所以俗称做启动盘,所以他必须知道磁盘的哪个扇区存放着操作系统的核心代码in,所以引导区把这个扇区放在磁盘上。区域,以及之后的许多许多扇区(取决于操作系统的大小)被读入内存,然后跳转到启动程序的位置。跳到哪里?这不像数字 0x7c00 那样经典。不同的操作系统肯定是不一样的,没必要提前规定。反正写操作系统的人可以自己设置一个,不要覆盖其他关键设备使用的区域。好的。

八、操作系统内核里写了什么

现在好了,经过几轮跳跳,终于跳到内核代码了,一起来回顾一下吧:

按下电源键,CPU会强制将PC寄存器的值初始化为0xffff0,即BIOS程序的入口地址(一跳转)

入口地址为跳转指令,跳转到0xfe05b位置开始执行(两次跳转)

在进行了一些硬件检测工作后,最后一步是将引导区的内容加载到内存0x7c00中,并跳转到这里(三次跳转)

引导区的代码主要是加载操作系统内核,跳转到加载的地方(四次跳转)

经过这四次连续的跳跃,我终于来到了操作系统的世界。剩下的内容可以说是整个操作系统课程中描述的原理,分段、分页、创建中断、设备驱动、内存管理。 、进程管理、文件系统、用户界面等。

您可能在操作系统课程中或多或少听说过这些术语。如果你努力学习,你必须知道大体原理,但是像作者一样,一个从头到尾研究过linux内核源代码的铁杆狗,换句话说,这些概念不仅仅是书本上无聊的概念,而是活在操作系统的每一行代码中。有的展示了作者无比的智慧,有的让我看到了作者因硬件设置而投降。 .

如果这篇文章引起了你对操作系统的好奇,建议你也抽空读一读,和我一起入坑,你会发现一个新的世界向你打开了

九、参考文献

好了,这次真的要讲完了,相信如果你真的看完了全文,可以说对电脑的启动过程有了更具体的了解。如果你想深入细节,也就是了解整个过程的每一个点,那就是很多工作了。

初学者推荐两本书,可以按顺序阅读,祝大家坑:

Python猫技术交流群开放啦!既有国内一二线大厂的在职员工,也有国内外高校的学生。有十几岁的编程老手,也有刚上小学、中学的新人。学习氛围很好!想进群的同学,请在公众号回复“交流群”,获取猫哥的微信(拒绝广告党,如果你是的话!)~

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论