A20ライン問題 歴史的背景 始めの8088PCには20本のアドレスラインしかなく1メガバイトまでのメモリを扱えた。 しかし、セグメント:オフセットで指定できるアドレスの最大値はFFFF:FFFF。 これは0xFFFF << 4 + 0xFFFF = 0x10 FFEF になる。つまり、0xFFEFバイト余分なメモリを 扱えることになる。しかし、そのようなアドレスを使用しても8088PCにはアドレスラインが 20本しかないので0x100000を超えた分はラウンドアップされる。つまり、0x100001は 0x000001として解釈される。しかし、80286の時代になって24本のアドレスラインを 持つようになると、このようなラウンドアップは行われなくなる。(相変わらず指定できるのは 1メガバイト程度だが)このようなバージョンアップで当然互換性が問題になってくる。 8088時代のプログラムにラウンドアップを前提としてプログラムされたものがあったため、 80286で動かなくなってしまう。(0x000001を指定したつもりなのに0x100001を指定してしまった) そのような問題を解決するためにIBMはアドレスラインの21番目つまり、20番のアドレスラインを 有効にするかどうかを決められるようにした。・・・ここまではいいのだがこの設定を どういうわけかキーボードコントローラーの出力ポートの線で指定する事にしてしまった。 完全に(゚Д゚)ハァ?な決定である。 まとめると次のようになる。 ・IBMは下位互換性を保つため20番のアドレスラインを有効にするか無効にするかを決めることが できるような設計にした。 ・しかし、その設定はどういうわけかキーボードコントローラーの出力ポート(P2)で 行うことになっている。ちなみにこの事実はインテルの解説書には書いてない・・・ 次のA20を有効にする処理をMONAのコードを元に説明する。 1)まず、割り込みを無効にする。設定している間にキーボードからの割り込みがあったら たまったもんじゃない。 cli 2)まず、ステータスレジスタを調べて入力バッファーが空いているかどうかを調べる。 入力バッファーが空いていれば、ステータスレジスタのビット1が0になる。それを 確認してコマンドを書き込む。コマンドは0xD1でIOポート0x60の内容を キーボードコントローラーからキーボードへの出力ポート(P2)に書き込む命令である。 a20enable: in al,0x64 test al,0x02 jnz a20enable mov al,0xD1 out 0x64,al 3)コマンドを送った後再び入力バッファーが空になるまで待つ。それから出力ポートに A20を有効にする内容を書き込む。 a20enable_1: in al,0x64 test al,0x02 jnz a20enable_1 ;wait every KBC cmd. mov al,0xDF out 0x60,al 基本的にはこれだけで十分である。