首页 > 解决方案 > 8086 复位向量高于 20 位,总线为 20 位

问题描述

如果地址 ( ) 超过 20 位总线的 1mb 限制,cpu 如何从地址0xfffffff0( ) 中获取指令?CS_base : 0xffff0000 + IP : 0xfff0

我已经阅读了其他帖子;他们只谈论 cs 寄存器是硬连线以获取0xffff0000基地址的事实,而不是总线限制

标签: x86cpu-architecturebootbiososdev

解决方案


最初(例如对于 8088、8086、80186),物理地址是 20 位(提供 1 MiB 的物理地址空间)。在上电和复位时,CS:IP 设置为“0xF000:0xFFF0 = 0xFFFF0”,固件的 ROM 位于物理地址空间的末尾(例如,在物理地址 0xFFFFF 结束)。

请注意,此值不是“超过 20 位”,因为“段:偏移”被转换为物理地址的方式(具体而言,“物理 = 段 * 16 + 偏移”)。

另请注意,对于不适合 20 位的物理地址,最高位被丢弃以使其适合 20 位(例如“0xFFFF:0xFFFE = 0xFFFF*16 + 0xFFFE = 0x10FFEE = 0x0FFEE”)。这导致了特殊的骇客(“A20 门”)通过在 80286 发布时禁用第 21 个地址线(A20)来保持向后兼容性(物理地址大小增加到 24 位,提供 16 MiB 的物理地址空间)。

80286 发生的另一个变化是(为了支持保护模式)段寄存器(最初只是一个 16 位整数)获得了一些隐藏部分——主要是一个隐藏的“段基”值被添加​​到段寄存器中,因此 (在受保护模式下)您拥有加载到段寄存器中的可见值,并且段的详细信息(基地址,限制)是从表(全局描述符表或本地描述符表)加载的,而不是直接由加载的值暗示进入段寄存器,物理地址计算被更改为使用隐藏值(例如“physical = segment.base + offset”),并且在实模式下,段基数是在段加载时设置的(例如“segment.base = value * 16") 以便在实模式下一切正常。

后来(从 80386 开始)物理地址空间的大小增加了(首先是 32 位,然后是 36 位,然后是“架构最大 52 位”)。发生这种情况时,他们更改了在开机/重置时加载到 CS 隐藏部分的值。具体来说,可见部分保持不变(0xF000),但隐藏的“段基”部分设置为 0xFFFF0000,因此它实际上变为“0xFFFF0000+0xFFF0 = 0xFFFFFFF0”。此外,固件的 ROM 被移到了 32 位地址空间的末尾(例如,在物理地址 0xFFFFFFFF 处结束);并且(为了兼容性)复制了一部分 ROM(可能已解压缩)并放入 RAM 中的旧地址(以物理地址 0x000FFFFF 结尾),并且配置内存控制器以便写入“遗留 ROM 区域”

当然现在(对于 UEFI,理论上和/或一旦“混合 BIOS + UEFI”在明年永久不复存在)这可能会消失 - 无需将 ROM 的一部分复制到“遗留 ROM 区域”,也不需要将内存控制器配置为忽略对该区域的写入;我们可以从 0x00000000 到 0xBFFFFFFFF 拥有大的(3 GiB?)正常可用 RAM 区域。


推荐阅读