Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1846880
  • 博文数量: 184
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2388
  • 用 户 组: 普通用户
  • 注册时间: 2016-12-21 22:26
个人简介

90后空巢老码农

文章分类

全部博文(184)

文章存档

2021年(26)

2020年(56)

2019年(54)

2018年(47)

2017年(1)

我的朋友

分类: LINUX

2020-06-12 20:15:39

由于os这块我学的比较杂,所以发博的时间可能不太固定,可能有时候会底层和顶层混合着来,就需要各位看官老爷多多海涵了哈~

BIOS,是basic input output system的缩写,用于在电脑启动初期检测基本的硬件的程序(你装系统,刚开机,疯狂按某个组合键出现的那个界面),随后加载grub,grub之后会把操作系统内核加载进来,并运行内核,最后就是内核启动,并将最终界面展示在你面前了,这一节应该是会先把内存分段简单说下,接下来应该就是讲讲bios里面的东西了


言归正传,先简单的说说x86当中的分段机制

我们知道,当我们写代码的时候,最终会被编译成二进制可执行文件,执行这个文件就可以把你刚刚实现的功能展示出来;编译器在把源文件编译成目标文件的时候,会把文件划分成各个段,数据一个段,代码一个段,还有堆啊,栈啊这些东西。但是,CPU是不知道这些东西的存在的,它只会去物理地址上拿指令,然后执行,这就要求我们的程序必须时刻保证CPU拿到的是指令,而不是其他东西,这就是上面的可执行文件中要区分那么多段的原因了。分了段之后,我们只需要记住这个段的起始位置,以及每一条指令相对于这个起始位置的偏移量就能够精确定位一条指令或者一条数据了,而且在编译的时候,只需要记录相对偏移量就好了,段的起始地址交给os去做,我们只管写程序。在程序真正运行起来之前,操作系统会把可执行二进制文件当中各个段的信息放到对应的寄存器当中,这样,当这个程序想要执行某条指令的时候,只需要把对应寄存器(CS)当中存储的物理地址拿出来,加上偏移量(存在指令寄存器IP当中),就能够在物理地址当中找到相应的地址了

在计算机刚开始启动的时候,为了兼容,不管你是32位机器还是64位的,可用地址线总共只有20根(这时,由于寄存器都是使用16位的,为了将两个16位寄存器的值合并为一个20位地址,办法就是:物理地址 = 段寄存器中内容<< 4 + 偏移寄存器当中的地址,这样会有回环问题,需要程序实现者自己保证了,当机器起来之后,寻址空间就是32位或者64位了,组合方式换成加法就行了),寻址空间只有1M,这1M的空间很宝贵,需要实现bios的自举,但是由于内存中的东西掉电就没了,于是大牛们就把这1M当中的高64K地址空间,映射到一个ROM当中,这货不管断电与否,存储内容都不会丢失的。当按下电脑启动键,CPU会将其内部一些东西置位,比如代码段寄存器会置位为0xffff,其他的寄存器会置位为0,这样CPU的第一条指令就在0xffff0,正好在ROM当中,执行这个ROM当中的程序就实现了基本的输入输出自检,其最后的工作就是在外部存储设备读取更多的指令供CPU处理,它会把启动盘(最后两字节分别为0x55, 0xAA)当中的第一个扇区加载到一个固定位置,然后在那个位置开始执行指令就行了,之后的工作就交给启动盘上的程序了,BIOS的工作就完成了~
阅读(1095) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~