8086 复位向量高于 20 位,总线为 20 位

8086 Reset vector above 20 bits with buses of 20 bits

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

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

8086 有一个 20 位总线,复位时 CS 寄存器设置为 0xffff,IP 设置为 0x0000,使物理地址为 0xffff0,即 20 位。 20 位可寻址 space CPUs 具有 16 位 CS 和 IP 寄存器,因此您在问题中的寄存器值(CS:0xffff0000 + EP:0xfff0)对于 8086 [=12] 不正确=].

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

请注意,由于 "segment:offset" 转换为物理地址的方式 (具体来说,"physical = segment * 16 + offset"),此值不是 "above 20 bits" .

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

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

后来(从 80386 开始)物理地址 space 大小增加了(先是 32 位,然后是 36 位,然后是 "architectural maximum of 52 bits")。发生这种情况时,他们更改了加载到 power-on/reset 处 CS 隐藏部分的值。具体来说,可见部分保持不变 (0xF000),但隐藏 "segment base" 部分设置为 0xFFFF0000,因此它实际上变为“0xFFFF0000+0xFFF0 = 0xFFFFFFF0”。此外,固件的 ROM 被移动到 32 位地址的末尾 space(例如,在物理地址 0xFFFFFFFF 处结束);并且(为了兼容性)复制(可能解压缩)一块 ROM 并将其放入 RAM 中的旧地址(以物理地址 0x000FFFFF 结尾),并且内存控制器被配置为忽略对 "legacy ROM area" 的写入(这样它的行为仍然像 ROM,但速度更快,因为 RAM 比 ROM 快)。

当然现在(对于 UEFI,理论上 and/or 一旦 "hybrid BIOS+UEFI" 明年永久不复存在)这可能会消失 - 无需将 ROM 的一部分复制到 "legacy ROM area" 并且不需要配置内存控制器来忽略对该区域的写入;我们可以拥有从 0x00000000 到 0xBFFFFFFFF 的大(3 GiB?)正常可用 RAM 区域。