アセンブラ入門で一番最初に学んだセグメントの概念を
思い出してください。16bitレジスタで20bitのアドレスを表現するために、セグメントと、オフセット
というものを用いました。これはオフセットアドレスとセグメントアドレスをずらして足すという
ものでした。
そこでちょっと考えてください。1MBytesで一番上位、すなわちFFFFFhを表すためには、
[F000h:FFFFh]と表します。また、[FFFFh:000Fh]とも表せます。では、[FFFFh:0010h]という
アドレスは、どこを指すのでしょうか?
これはCPUによります。8086, 80186(, V30)では、これは[00000h=0000h:0000h]を指します。
つまり、1周して、最初に戻ってしまうわけです。(これをメモリーラップあるいはラップアラウンド
と言います。) ところが、80286以上のCPUでは、
[10000h=FFFFh:0010h]を指します。すなわち1MBytes以上のメモリー空間に、MS-DOSから
直接アクセスできることを表します。
したがって、MS-DOSから直接アクセスできる最大のメモリーは、[FFFFh:FFFFh]、すなわち
[10FFEFh]番地までです。したがって、FFEFh=65519バイトだけ余計に使えるのです。そして
この65519バイトの領域をHMAといいます。
しかし、このHMAは80286以上であれば、どんな場合でもアクセスできるわけではありません。
80286以上のCPUに存在するアドレスバス32本のうち、21番目のアドレスバスが有効になっていないと
使用できません。この21番目のアドレスバスのことを「A20ライン」と呼びます。80286以上の
CPUでもA20ラインが無効だと、8086などと同様にラップアラウンドして、メモリーの下位に
戻ってしまいます。逆にA20ラインが有効だと、HMAにアクセスできます。このA20ラインの
有効化、無効化はXMSドライバーのファンクションを使用します。
コンベンショナルメモリーの管理は、セグメント単位で行っていました。しかし
HMAはセグメント単位で管理ができません。なぜならばセグメントアドレスはFFFFhと
決まってしまっているからです。また64KBytes弱という、それほど大きくないメモリーを
、何人かで共有できるようにMS-DOSを改良すると、その分MS-DOS自体が使用するメモリーが
大きくなってしまい、本末転倒になってしまうため、「HMAは基本的に1人しか使用できない」
という仕様にしました。
「基本的に」と言うのは、「1人」と限定するとあまりにも不親切なため、簡単な
チェックでHMAの管理をしているからです。しかし、HMAを何人かで使用するのは、
不具合が生じる原因になるようです。また、デバイスドライバーや常駐プログラムは
何人かで使用できますが、アプリケーションはHMAが誰も使っていない場合にしか使用できません。
ちなみにHMAを一番効率よく使用しているのは、MS-DOS自身をHMAに常駐させるときの
ようです。