A20线在保护模式下扮演什么角色?

3
我正在学习x86保护模式,刚刚了解了GDT。之前我学过,在进入保护模式(即:使用所有32位地址线)之前,必须启用A20门。所以,启用A20的代码必须在16位中,对吗? 最近当我浏览wiki.osdev网站时,发现启用A20的代码是用x86汇编语言编写的。X86汇编产生的32位操作码不能在16位模式下加载,对吗? 如有可能,请解释一下。 谢谢。

有16位和32位的x86汇编语言。您可以为任一模式汇编x86汇编代码。 - fuz
所生成的代码类型取决于汇编器和汇编指令以及汇编标志,同样也取决于实际使用的操作码。 - David Hoelzer
2个回答

12
8086寻址模型包括一个16位段和一个16位偏移量,结合起来表示为segment * 16 + offset
最小地址是000000h,最大地址是10ffefh
虽然后者实际上是21位值,但CPU只有20位地址总线,因此可访问的最大地址是0fffffh1
超过0fffffh的地址将被简单地包装成2,因此10ffefh0ffefh的别名。
一些程序开始依赖这一点。
当80286推出时,它有24位地址总线。
10ffefh这样的地址不再简单地回绕了。
在当时,模拟旧行为需要太多的晶体管(10ffefh无法使用AND屏蔽),因此引入了A20掩码。
顾名思义,地址线20即第21位与8055/8042芯片中特定寄存器的特定位进行了AND运算。
BIOS会在启动时清除该位,从而强制第21位为零,以模拟旧的行为。
如果不启用A20,则每个物理地址的第21位始终为零。
在保护模式下,可以使用平面模型启用A20,这是最接近“32位模式”的东西,但需要小心地放置代码位置。
x86汇编语言可通过告诉汇编器目标大小而同样用于生成16位或32位代码。
1例如,给出段0f000h和偏移0ffffh
2第21位被简单丢弃。3 简单来说,如果你正在编写16或32位代码。

4
尽管你的回答中已暗示了这一点,但为了清楚起见,我还是想说一下。如果不启用A20线,所有以奇数兆字节(1024k)边界开头的内存区域都将映射到下方相邻的偶数兆字节区域。当然,其副作用是有一半的可用物理内存地址将无法访问。 - Michael Petch
能否详细解释一下,Michael Petch先生? - Panther Coder
2
@PantherCoder 迈克尔表示,范围为100000h - 1FFFFFh将映射到000000h - 0FFFFFh,范围为300000h - 3FFFFFh将映射到200000h - 2FFFFFh,范围为500000h - 5FFFFFh将映射到400000h - 4FFFFFh等等。范围为000000h - 0FFFFFh200000h - 2FFFFFh400000h - 4FFFFFh等等不受影响。这是由于A20被强制归零,有效地使地址中的一位失效(32位->31位),从而减少了地址空间。取一个随机的32位数,看看当屏蔽第20位时会发生什么。 - Margaret Bloom

-2
问题在于如果A20门关闭,第20位地址位将被设置为零。例如,如果您想访问地址0x000100ab,则实际上访问的是0x000000ab,或者如果您想访问0x06570021,则实际上访问的是0x0656021,无论您是处于保护模式还是实模式。原因是在实模式下,您可以使用段:有效地址组合FFFF:00bb生成占用超过20位的物理地址,例如0x001000ab,但8086会将其截断为0x000ab,而80286或更新版本将在A20门打开时访问0x001000ab,这对于依赖该“特性”进行包装的程序(如某些BIOS代码)非常不利。
当然,关闭A20门会完全干扰您在保护模式下超过20位地址的操作,这就是为什么在切换到保护模式时必须确保它已打开的原因。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接