- 实模式下1M内存
- 比特,字,字节单位
- BIOS 是怎么启动的
- 找到 BIOD 的入口地址
- 找到 jmp指令
- 小小总结
如果你亲自动手重载过系统你就听过 BIOS 这个名词。BIOS 全称叫 Base Input & Output System ,也就是基本输入输出系统。
实模式下1M内存
在很久以前,Intel 8086 有 20 条地址线,因为 220=1048576=1MB,所以,这 20 条地址线可以访问 1MB 的内存。如果用 16 进制来表示就是 0x00000 ~ 0xFFFFF
。
这里先大概预览一下实模式下的内存布局表
比特,字,字节单位
计算机由几亿万个位(bit
)组成,每个字节存储的都是 0,1 二进制.一般 8 个位组成一个字节(byte
),当然不同机器不一样。
每个字节类似一个存储单元,但是这样的一个存储单元有点小,所以有些机器把多个字节连接在一起,组成一个更大的内存单位,称为【字】。一个字一般由 2 个 或者 4 个字节组成。所以呢,每个字包含了更多的位,每个字可以容纳的无符号整数范围是 0 ~ 4294967295
(232-1),可以容纳的有符号整数范围是 -2147483648
(-231) ~ 2147483647
(231-1)。
- 1字节(
Byte
) = 8位(bit
)- 1 千字节(
KB
) = 1024字节(B
)- 1 兆字节(
MB
) = 1024K (1024KB
)
内存地址 0 ~ 0x9FFFF 的空间范围是 640KB,这个范围的地址对应到 DRAM(动态随机访问内存,断电即丢失),也就是我们插在主板的内存条,但是,内存条的内存不等于全部的物理内存。
上表中的 0xF0000 ~ 0xFFFF
,这 64KB 内存就是 ROM (只读存储),这里存放的是 BIOS 的代码 (其实这里存储的只是跳转指令)。
我们先来看下面这张图,0xF0000 ~ 0xFFFF
这段地址可以分为 0xF0000 ~ 0xFFFEF
+ 0xFFFF0 ~ 0xFFFFF
,其中 0xFFFF0 ~ 0xFFFFF
这段 16 字节,是 BIOS 的入口地址,此处的内容是 跳转指令 jmp f000: e05b
。其中 BIOS 的作用是 检测、初始化硬件 和 建立中断向量表,这里的建立操作对硬件来说就是 IO 操作。
从上图可以清楚看出 ROM 只有 64KB,所以能够实现所有的 IO 操作非常有限,这也正是在实模式下为什么计算机只能运行硬件 IO 的基本操作。这应该也是 BIOS 为什么叫基本输入输出系统的原因吧。
回到一开始的问题,为什么在 CPU 眼里主板插上的内存条的内存不是“全部内存”呢?
这其实是由[地址总线]的宽度决定的,因为地址总线的宽度决定了可以访问的内存空间大小,就比如我们以前用的 32 位的电脑,其实它的地址范围就是 4GB (232=4294967296),所以你电脑如果还是 32位 的,那就算买的内存条大于 4GB 也不会有什么本质的作用。
注意,刚刚说的是寻址范围为 4GB,但是并没有说它一定会寻址到哪里,所以寻址范围不一定是物理地址。这是怎么回事呢?
因为在计算机中,除了主板上的内存条外,还有其他设备也需要通过地址总线来访问,就比如显存,硬盘控制器等。试想,如果把所有的地址总线都拿来给主板上的内存条用,那么其他设备怎么办呢?是吧。所以说,地址总线需要将一部分内存预留出来,剩下的内存才是指向 DRAM(物理内存)。
所以不要还以为电脑中内存条越大越好,还得看你电脑中地址总线的宽度,如果你电脑的地址总线的寻址范围只有 8G,那你买个 16G 的内存条有什么用呢?
BIOS 是怎么启动的
找到 BIOD 的入口地址
BIOS 是计算机上第一个运行的软件,那么既然是第一个软件,那它肯定不能自己加载自己了,所以 BIOS 是由硬件加载的。这个硬件也就是我们前面提到的 只读存储器 ROM。因为是只读的,所以里面的内容是不可以更改的,也可以说 BIOS 的工作是一成不变的。当然你如果要刷机情况除外。
从上图可以很清楚看出 BIOS 写在 ROM,然后 ROM 被映射到整个 1M (实模式)的顶部,也就是之前说的 64KB 那里。然后 BIOS 的入口地址是 0xFFFF0。
好了,现在找到 BIOS 的入口了,那么 CPU 如何执行它呢?也就是说 CPU 的 cs:ip寄存器怎么将一串数字组织成 0xFFFF0 呢?
找到 jmp指令
这里先注释一点,CPU 给一串字符串给地址总线,地址总线将这一字符串映射成地址,CPU 才能访问该地址。
CPU 的访问内存需要涉及到内存分段机制,就是CPU 需要用 段基地址 + 偏移地址 才能找到物理地址。这里注意,在实模式下,段地址需要乘于 16,也就是向左移 4 位才能与偏移地址相加。
计算机在开机之后,CPU 的cs: ip寄存器被强制初始化为 0xF000: 0xFFF0,也就是 cs 寄存器的值是 0xF000,ip 寄存器的值是 0xFFF0,也就是段基地址是 0xF000,段内偏移地址是 0xFFF0,这个地址组合出来就是 0xFFFF0。
这里简单介绍下上面是怎么计算出来的。0xF000 转成二进制是 1111 0000 0000 0000 ,然后左移 4 位之后变成 1111 0000 0000 0000 0000 0000 ,再加上 0xFFF0(1111 1111 1111 0000) 等于 1111 1111 1111 1111 0000(FFFF0)。
0xF000 处存储的还是跳转指令 jmp f000: e05b
,也就是下一条要执行的指令。也就是说跳转到下一条要执行的指令。这就是 BIOS 代码开始的地方。接下来 BIOS 就可以开始工作了。
小小总结
- 主板内存条的内存不一定是实际的物理内存,这和地址总线的宽度有关,因为地址总线的宽度决定寻址的范围。而且不仅仅是主板上的内存条需要访问地址总线,其他设备也需要访问,所以地址总线需要预留出一部分地址空间出来给其他设备访问。因此我们买的 4GB 的内存条,在电脑看到的可能只有 3.8GB。
- BIOS 的起始地址是 0xFFFF0,CPU 通过地址总线映射到这个地址,然后 CPU 访问该地址并执行它,这个访问过程需要用到内存分段机制,即 段基地址+偏移地址=物理地址。
参考《操作系统真象还原》《王爽的汇编语言》