我正在浏览x86的保护模式部分。我刚刚了解了GDT。之前,我已经研究过进入保护模式(即:使用所有32位地址线)必须启用A20门。 那么,启用A20的代码必须是16位吗? 最近,当我浏览wiki.osdev网站时,我发现启用A20的代码是用x86汇编编写的。 X86汇编产生的32位操作码无法以16位模式加载吗?
请尽可能解释。 谢谢。
答案 0 :(得分: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芯片中特定寄存器的特定位进行AND运算。
BIOS在启动时清除该位,从而将第21位强制为零,从而模拟旧的行为。
如果你不启用A20,每个物理地址的第21位将始终为零。
可以在保护模式下使用扁平模型启用A20,这是最接近" 32位模式"但是需要小心将代码放入内存。
通过告诉汇编程序目标大小,x86程序集可以同样用于生成16位或32位代码。 1 例如,由 0f000h 的一段和 0ffffh 的偏移量给出。
2 第21位被简单地丢弃了
3 如果您要编写16位或32位代码,请简单地说。
答案 1 :(得分:-2)
问题是如果A20门关闭,则第20个地址位设置为零。例如,如果您想访问地址0x000100ab,您实际上是访问0x000000ab,或者如果您想访问0x06570021,您实际上访问0x0656021,无论您是处于保护模式还是实模式。这样做的原因是,在实模式下,您可以使用例如0x001000ab产生一个物理地址,该地址需要20比特,如0x001000ab。段:有效地址组合FFFF:00bb,但8086将其截断为0x000ab,而80286或更新版本如果打开A20 Gate则访问0x001000ab,这对于依赖于它的程序(如某些BIOS代码)是不利的#34;特征"
当然,一个封闭的A20门在你保护模式下完全与你混淆20位地址这就是为什么你必须确保在你切换到保护模式时打开它的原因。