进入保护模式之前,这里还涉及一个历史遗留问题,那就是处理器的第 21 根地址线,编号 A20。“A”是Address的首字符,就是地址,A0是第一根地址线。在8086处理器上运行程序不存在A20问题,因为它只有20根地址线。
实模式下的程序只能寻址1MB内存。当逻辑段地址达到最大值0xFFFF时,再加一,就会因进位而绕回到 0x0000。
到了80286时代,处理器有24条地址线,地址回绕不灵了。比0x0FFFFF大的数是0x100000,80286 处理器可以维持 24 位的地址数据,进位不会被丢弃。为了能在80286处理器上运行8086程序而不会因地址线产生问题,IBM决定在主板上动手脚。
问题的解决办法很简单,只需要强制第21根地址线(A20)恒为“0”就可以了。这样,0x0FFFFF加1的进位被强制为“0”,结果是0x000000(24位地址线);再加1,是0x000001,······,永远和实模式一样。
如图 11-6 所示,IBM公司使用一个与门来控制第21根地址线A20,并把这个与门的控制阀门放在老式键盘控制器内(刚好有个空闲引脚,现在的USB键盘已经不适用),端口号是0x60。向该端口写入数据时,如果第1位是“1”,那么,键盘控制器通向与门的输出就为“1”,与门的输出就取决于处理器A20是“0”还是“1”。当它是0,则位20以及以上地址都被清除,就能实现兼容性。
不过这种方式很麻烦,因为要访问键盘控制器,需要先判断状态,要等待键盘控制器不忙,至少需要十几个步骤,需要的指令数量很多。
所以从80486处理器开始,处理器本身就有了A20M#引脚,意思是A20屏蔽(A20 Mask),它是低电平有效的。
如图 11-7 所示,输入输出控制器集中芯片ICH的处理器接口部分,有一个用于兼容老式设备的端口0x92,第7~2位保留未用,第0位叫做INIT_NOW,意思是“现在初始化”,用于初始化处理器,当它从0过渡到1时,ICH芯片会使处理器INIT#引脚的电平变低(有效),并保持至少16个PCI时钟周期。通俗地说,向这个端口写1,将会使处理器复位,导致计算机重新启动。
端口0x92的位1用于控制A20,叫做替代的A20门控制(Alternate A20 Gate,ALT_A20_GATE),它和来自键盘控制器的A20控制线一起,通过或门连接到处理器的A20M#引脚。和使用键盘控制器的端口不同,通过0x92端口显得非常迅速,也非常方便快捷,因此称为 Fast A20。
当 INIT_NOW 从 0 过渡到 1 时,ALT_A20_GATE将被置“1”。这就是说,计算机启动时,第21根地址线是自动启用的。A20M#信号仅用于单处理器系统,多核处理器一般不用。特别是考虑到传统的键盘控制器正逐渐被 USB 键盘代替,这些老式设备也许很快就会消失。
端口 0x92 是可读写的,第 40~42 行,先从该端口读出原数据,接着,将第2位(位1)置“1”,然后再写入该端口,这样就打开了A20。为了能够访问和使用1MB以上的物理内存,我们需要开启A20地址线。