3

我正在经历 x86 的保护模式部分。我刚刚了解了 GDT。之前,我研究过要进入保护模式(即:使用所有 32 位地址线)必须启用 A20 门。那么,启用 A20 的代码必须是 16 位的吧?最近浏览 wiki.osdev 站点时,发现启用 A20 的代码是用 x86 汇编编写的。X86 程序集产生无法在 16 位模式下加载的 32 位操作码,对吗?

如果可能,请解释。谢谢你。

4

2 回答 2

11

8086 寻址模型设想了一个 16 位段和一个 16 位偏移量组合为segment * 16 + offset.
最小地址为000000h,最大地址为10ffefh
虽然后者在技术上是 21 位值,但 CPU 只有 20 位地址总线,因此可访问的最大地址是0fffffh 1

0fffffh上面的地址只是简单地包裹在2周围,所以10ffefh是 0ffefh 的别名
一些程序开始依赖它。

当 80286 出来时,它有 24 位地址总线。
10ffefh这样的地址不再环绕。
当时模拟旧行为需要太多晶体管(10ffefh不能用 AND 屏蔽),因此引入了 A20 掩模。

顾名思义,地址线 20(第 21 位)与 8055/8042 芯片中特定寄存器的特定位进行“与”运算。
BIOS 在启动时清除该位,从而将第 21 位强制为零,模拟旧行为。

如果不启用 A20,则每个物理地址的第 21 位将始终为零。


可以使用平面模型在保护模式下启用 A20,这是最接近“32 位模式”的东西,但需要小心将代码放入内存中。

x86 汇编可以同样用于生成 16 位或 32 位代码,只需告诉汇编器目标大小即可。


1例如,由 0f000h 的段和0ffffh偏移量给出。2第 21 位被简单地丢弃。3简单地说,如果您正在编写 16 位或 32 位代码。

于 2016-07-18T18:12:25.970 回答
-2

问题是如果 A20 Gate 关闭,第 20 个地址位将设置为零。例如,如果你想访问地址 0x000100ab,你实际上是在访问 0x000000ab,或者如果你想访问 0x06570021,你实际上是在访问 0x0656021,无论你是处于保护模式还是实模式。这样做的原因是,在实模式下,您可以使用例如段:有效地址组合 FFFF:00bb 生成一个占用更多 20 位的物理地址,例如 0x001000ab,但 8086 将其截断为 0x000ab 而 80286 或更新版本如果 A20 Gate 打开,将访问 0x001000ab,这对依赖于“功能”的程序(如某些 BIOS 代码)不利。

当然,关闭的 A20 Gate 会完全弄乱你,因为它们是保护模式下的 20 位地址,这就是为什么你必须确保在切换到保护模式时它已打开的原因。

于 2017-03-17T18:53:52.223 回答