我正在经历 x86 的保护模式部分。我刚刚了解了 GDT。之前,我研究过要进入保护模式(即:使用所有 32 位地址线)必须启用 A20 门。那么,启用 A20 的代码必须是 16 位的吧?最近浏览 wiki.osdev 站点时,发现启用 A20 的代码是用 x86 汇编编写的。X86 程序集产生无法在 16 位模式下加载的 32 位操作码,对吗?
如果可能,请解释。谢谢你。
我正在经历 x86 的保护模式部分。我刚刚了解了 GDT。之前,我研究过要进入保护模式(即:使用所有 32 位地址线)必须启用 A20 门。那么,启用 A20 的代码必须是 16 位的吧?最近浏览 wiki.osdev 站点时,发现启用 A20 的代码是用 x86 汇编编写的。X86 程序集产生无法在 16 位模式下加载的 32 位操作码,对吗?
如果可能,请解释。谢谢你。
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 位代码。
问题是如果 A20 Gate 关闭,第 20 个地址位将设置为零。例如,如果你想访问地址 0x000100ab,你实际上是在访问 0x000000ab,或者如果你想访问 0x06570021,你实际上是在访问 0x0656021,无论你是处于保护模式还是实模式。这样做的原因是,在实模式下,您可以使用例如段:有效地址组合 FFFF:00bb 生成一个占用更多 20 位的物理地址,例如 0x001000ab,但 8086 将其截断为 0x000ab 而 80286 或更新版本如果 A20 Gate 打开,将访问 0x001000ab,这对依赖于“功能”的程序(如某些 BIOS 代码)不利。
当然,关闭的 A20 Gate 会完全弄乱你,因为它们是保护模式下的 20 位地址,这就是为什么你必须确保在切换到保护模式时它已打开的原因。