x86 - 8086 复位向量高于 20 位,总线为 20 位
问题描述
如果地址 ( ) 超过 20 位总线的 1mb 限制,cpu 如何从地址0xfffffff0
( ) 中获取指令?CS_base : 0xffff0000 + IP : 0xfff0
- 我知道 cs 寄存器以基地址开头
0xffff0000
- 但我不明白总线如何仅与 20 位总线通信此地址
我已经阅读了其他帖子;他们只谈论 cs 寄存器是硬连线以获取0xffff0000
基地址的事实,而不是总线限制
解决方案
最初(例如对于 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 区域。
推荐阅读
- java - 链表返回值
- mysql - Node Express MySQL 多路由
- r - 在 R 中使用 glm 阶跃函数预测新数据
- javascript - 组织具有重复元素的多维数组
- python - 有没有办法在 for 循环上运行优化器?
- c++ - C ++从文件中读取字符,计算每个字符并排序
- python - 在 jupyternotebook 中使用 pyviz 作为表单,将输入放入嵌套列表并显示内容
- xml - 嵌套的 XML/JSON 结构标签,定义结构的正确方法是什么?
- python - 使用正则表达式删除字符串中的数字
- python-3.x - 使用 AND、OR、NOT 交换变量值的代码是什么