IA32体系架构
CPU的结构组成: 寄存器有哪些?通用寄存器、段寄存器、eflags寄存器、段描述符缓冲寄存器、GDTR寄存器、IDTR寄存器 GDTR寄存器专门用来存储内存地址及大小,48位宽 控制寄存器CR0-CR7 我们用到的有CR0 CR3 CR3又被称为页目录基址寄存器(PDBR)32位 指令指针寄存器IP
CPU工作原理:从CS:IP指向的地址处取指,然后将该指令作为指令译码器的输入,对该指令编译,然后给CPU的ALU,执行该指令,简单概括为取指、译码、执行
CPU通过地址总线访问某个地址时,会映射到不同的物理硬件,例如访问0xF000-0xFFFF这个地址范围就是访问BIOS,访问0xA0000-0xC7FFF这个地址范围就是访问显卡
CPU每执行一条指令,就会改变eflags寄存器中的某些位,例如做算术运算时如果有进位或借位时,就将CF(Carry Flag)位置为1
对于条件跳转指令,其跳转的条件就取决于eflags寄存器中的值
内存结构: F0000 - FFFFF 64KB BIOS代码 C8000 - EFFFF 160KB 硬件适配器的ROM或内存映射式I/O A0000 - C7FFF 160KB 显示适配器相关 9FC00 - 9FFFF 1KB 扩展BIOS数据区 500 - 9FBFF 约639KB 可用区(MBR会加载到7C00-7DFF之间) 400 - 4FF 256B BIOS数据区 0 - 3FF 1KB 中断向量表
有的朋友可能会有这样的疑问:既然500 - 9FBFF全都是可用区,为什么MBR还可以加载到这里?如果后来加载的程序把MBR覆盖了怎么办? 答案:不用管,因为MBR在加载完内核加载器,再跳转过去之后就没有用了,只要是在这个时间节点之后覆盖它,就没关系
BIOS这个程序不需要被专门加载,在计算机出厂时就把它写入到了ROM中,ROM中的内容通常不可以改变,同理:
我们装了虚拟机后,BIOS也已经写入了虚拟机的ROM中,因此我们开发操作系统时,不需要编写BIOS的地址映射区(即0xF000-0xFFFF)里的内容
但是0xF000-0xFFFF里面到底放了什么东西,它的工作原理是怎样的,还是要了解,因为在加载操作系统之前都是走的这里的代码,例如我们想往屏幕上打印一些东西,该触发哪个中断,就需要调用BIOS给我们提供的接口,因此,我们最起码应该知道BIOS给我们提供了哪些接口以供我们调用
操作系统里有中断、进程、线程等概念,BIOS(Basic Input Output System基本输入输出系统)也是一个简易版操作系统,所以这些概念它也有一部分,例如操作系统中有中断的概念,BIOS里也有中断
同样的,BIOS和操作系统都有访问、读写内存的功能,上面我们提到BIOS有中断,它的中断向量表就位于0x000-0x3FF处,我个人猜测,这是CPU在执行BIOS中的代码时动态初始化到这里的,因为0x000-0x3FF已经处于RAM部分了,同样的,BIOS还会将0x400-0x4FF的范围作为自己的数据区
无论是对于BIOS还是操作系统,往屏幕上输出信息的原理都差不多:通过中断向控制屏幕显示的内存写入相应的指令或参数,然后显示器上就出现我们想要的信息
BIOS最终会将MBR加载到内存的物理地址0x7c00处,然后会通过一条jmp指令跳转到这里执行,此后就没有BIOS什么事了
CPU需要通过IO接口和各种IO设备进行通信,这里需要解释两个概念: IO接口:书中说这其实就是所谓的网卡、声卡、显卡等部件,不过我个人认为IO接口可能就是使这些硬件能够正常工作的一种驱动软件 通信:CPU总线都是以非常快的速度、并行的方式、按照某种格式来传输数据的,但IO设备有串行的有并行的、速度也比CPU要慢很多,数据格式千差万别,所以所谓的通信就是通过IO接口这一层,解决这些差异
每个IO接口,即网卡、声卡、显卡上有很多寄存器,CPU通过往这些寄存器上写入或读取内容来完成与它们的通信,这些寄存器在某些地方也叫端口,需要注意,此处的端口和TCP中的端口没有任何关系
当多个IO接口都想要和CPU通信时,需要一个仲裁设备,这个仲裁设备是南桥,南桥内部本身集成了一些对于计算机来说是必要的IO接口,例如硬盘、电源、USB等等
顺带一提,有南桥就有北桥,北桥主要协调内存和CPU之间的通信
上面提到了CPU在访问0xA0000-0xC7FFF这个地址范围时,就是访问显卡,也就是说这个地址其实是显存地址范围,因此我们基本可以理解为: CPU通过执行某些指令往这里写入一些内容,写完后发送中断信号通知显卡,显卡就从这里读出这些内容然后再做处理 或者说,显卡往这里写完数据之后同样也是发中断信号通知CPU,CPU就从这里读出处理的结果拿来自己用
BIOS加载跳转到MBR之后,便开始执行MBR里的代码,MBR共512字节,我们可以将其分为3部分: 0-445字节:代码区 446-509字节:硬盘分区表 510-511字节:结束标识 其中0-445字节部分主要检查分区表是否合法,并将内核加载器从硬盘加载到内存中执行
这里有两个问题:内核加载器在硬盘的什么位置?要把它加载到内存的什么位置?
第1个问题:我们现在的硬盘只有0柱面0磁头1扇区存放着MBR,其他地方都还没有规划,所以我们在放内核加载器时只需要保证不和MBR冲突即可,比如可以放到0柱面0磁头3扇区开始的位置 注:磁头、柱面、扇区这种编号方式(CHS)的话,习惯上扇区从1开始计数,如果以LBA编号方式的话,扇区从0开始计数 问题:内核加载器占用多少空间?
第2个问题:加载到500 - 9FBFF这段空闲区,即可