Expanded Memory Specification

**Expanded Memory Specification** (**EMS**) は、DOS上でのメモリ拡張手法。ロータス、インテル、マイクロソフトの3社が提唱したことから、その頭文字を付けて**LIM-EMS**とも呼ばれる。

## 概要
初期のDOSはIntel 8086向けに作られていたことから、8086が扱える最大のメモリ空間である1MB以上を扱うことが考慮されていなかった。8086が登場した当初は8ビットプロセッサの最大64KBの空間に比べると余裕があるように見えたが、ROMやVRAMの為に消費される空間を除いたメインメモリ空間は640KBまたは768KBに制限され、アプリケーションの規模が拡大し、また扱うデータが増大すると1MBでも不足するようになった。

やがて1MBを越えるメモリを扱える上位互換品である80286や80386が登場し、メモリモジュールが安価に手に入る時代に入ったが、リアルモードでどうやって使うかが問題になった。プロセッサをプロテクトモードで動作させれば1MBを越えるメモリを扱えたが、当時のDOSおよびそのアプリケーションは、多くの場合リアルモードで動作していた為である。

この壁を乗り越えるハード的な実装は幾つかあったが、代表的なのは後に統一規格として制定されたバンク切り換えによるメモリ拡張方式**EMS**である。EMSを使用するソフトではデータを16KB - 64KBの窓を通してアクセスする為、データの分解・再結合をしなければならず、またEMSを通常メモリのように透過的に扱うライブラリも無かった事から、やや煩雑なプログラミングをする必要があった。（コード領域をEMSに展開し、コンベンショナルメモリの負担を軽減するコンパイラはあった）。 80386からは仮想86モードを使ったソフトウエア的なEMSの実装が一般的となった。

## 基本概念
*"EMSマネージャ"を通じてメモリ空間の取得・開放、バンク切り換え等を行う。
*16KBytes単位でバンク切替を行い、これをページと呼ぶ。
*8086でアクセス可能な1Mbytesの範囲内に"ページフレーム"区画を設ける。
*ページフレームは、ほとんどの場合4ページ = 64Kバイト(バージョン4.0)の連続した領域。
*EMSマネージャは、要求のあったページをページフレームに出現させる。
*そのため、各種操作は隠蔽され、ユーザは気にする必要が無い。
*対応するメモリ総量は32Mバイト(2048ページ)まで。
*主な版として3.2, Enhanced EMS 3.2, 4.0がある。4.0では特にWindows 2.x向けの拡張を行った。
CPUやメモリバスの変遷に伴い、いくつかの実装方式があった。

## 実現方法

### ハードウェアEMS
バンク切替機能を持つ、専用メモリカードを拡張バスに接続する。バンク切替等の操作は、ハードウェア的に行われるので高速。また、8086・80186・V30といった、アドレスバスが20bitのCPUでもEMSを使用できる。純粋なハードウェアEMSを80286以降搭載のコンピュータに増設しても、プロテクトメモリとしては使用できないため、どちらも使用したい場合は"二重投資"となる。そのため、カード上のスイッチ切り替えにより、"拡張バス接続のプロテクトメモリ"としても使用できるEMSカードも存在した。

### ソフトウェアEMS
80286以降のCPUで使用可能。プロテクトメモリを用いてEMSのエミュレーションを行う。EMSマネージャは、バンク切替指令を受けると、プロテクトメモリからページフレームにページをコピー/書き戻しする。このオーバーヘッドのため低速である。EMSマネージャを組み込まない場合は、プロテクトメモリはそのまま使用できるので、汎用性がある。

一般的にソフトウェアエミュレーション方式のEMS（ソフトウェアEMS）といえばプロテクトメモリを使ったものを指すことが多いが、その他のエミュレーション方式についても併記する。

PC-9800シリーズ用の一部のEMSマネージャは、プロテクトメモリの代わりにI・Oバンクメモリを利用できた(ページフレームのアドレスはハードウェアEMSの有無により異なる)。バンクメモリを利用する場合は8086/V30でも使用できる。

また、プロテクトメモリの代わりに補助記憶装置（ストレージ）上のファイルを用いるドライバもある。メモリの代わりにファイルにアクセスするため、さらに低速であるが、ドライバによっては8086/8088などでも使用できる。HP200LX(CPUは80C186)では、この方法によりEMSが使用できる。ページフレームをメインメモリ空間に確保し、ストレージに充分な空き領域があれば、追加ハードウェアは不要である。

* LXEMM (HP200LX用) など

### 仮想86EMS
80386以降のCPUで使用可能。IA-32の仮想86モードを用いてEMSを実現する。EMSマネージャは、CPUのメモリマッピング機構を用いて、（プログラムから見て）ページフレームにプロテクトメモリ上のページを出現させる。ソフトウェアEMS同様の汎用性があり、ページ切替も高速。また、汎用拡張バスではなくメモリ専用バス上のメモリを使用可能なために最も高速である。ただし、仮想86モードはプロテクトモードの1タスクである（独立した動作モードではない点に注意）ため、プロテクトモードを使用した際に発生するのと同等の処理速度の低下がある。特に割り込みとI/Oポートへのアクセスでこの速度の低下が顕著となる。

DOS用ソフトウェアの互換性のために、Windows 9x系まではDOSモード用にEMM386が用意されていた。また仮想86モードに対応したWindowsのDOSプロンプトでは、Windowsの機能により仮想EMSが提供される。特にDOSモードを持たないWindows NT系ではDOSプロンプト上で動作するアプリケーションに限られるが、その後のWindowsにおいてもEMSの設定項目が存在する。

## 設定上の注意
メインメモリ（コンベンショナルメモリ）を圧迫せずにEMSを使用するためには、その範囲外となる空間にページフレームを設定する必要がある。しかし、この空間 (Upper Memory Area) はBIOS・拡張カードBIOS・VRAMが使用する空間である。

そのため、EMSを使用する際には、拡張カードBIOSを
*本体BIOS・VRAM・他のカードのBIOSと衝突しないように
*かつ、64KBytesの連続未使用領域が生じるように
設定し、そこをページフレームとしなければならない。

## ラージフレーム
PC/AT互換機におけるEMSの実装方法として、640KB以降のアッパーメモリにページフレームを設けるだけでなく、コンベンショナルメモリの上位アドレス(256KB:40000H以降など)にもページフレームを設けるラージフレーム方式がある(実装に仮想メモリマネージャを使うことが多かった)。特にWindows 2.0, Windows/286, Windows 3.0リアルモードではこの方法を使って、コンベンショナルメモリに常駐するDLLを切り替えることが可能で、この点において国産のPC-9801などに比べて快適なOS環境を実装していた(日本IBMで発売していたWindows 3.0Aのリアルモードでもこの機能は利用可能である)。

しかしながら下記に示すような欠点があったためにWindows 3.0以降は、次第に拡張メモリの標準をプロテクトメモリに移行していくことになる。

## EMSの欠点
* アドレス空間そのものを拡張する訳ではないので、同時に参照可能なアドレス空間の大きさは1Mバイトのままである。
* そのためプログラマはページフレームに出現しているページを常に把握してプログラムを開発する必要がある(メモリ管理に手間がかかる)。
* 仕様としてマルチタスク処理に必要なシステム保護機能（タスク毎に読み出し専用属性やコード実行専用属性つける等）が無かったため、マルチタスクおよび擬似マルチタスクOSの基本メモリ仕様としては不向きだった。
* DOS上で1Mバイトを超えるメモリを使用する方法としてはDOSエクステンダ等より低速である。(DOSエクステンダはバンク切り換え処理が不要である)
* 仮想86EMSは、他のプロテクトモードプログラムと共存するためにはVCPI等の規格に対応する必要がある。

## 参考文献
* 『MS-DOSメモリ管理ソフト技法-メモリ常駐ソフト&拡張メモリ活用プログラミング』（CQ出版、1990年）, ISBN 978-4-7898-3484-1
* 「インターフェース 1990年9月号」（CQ出版）
* 「インターフェース 1993年10月号」（CQ出版）
* Duncan, Ray (1992). *Extending-DOS*:A Programmer's Guide to Protected-Mode DOS (Addison-Wesley), ISBN 0-201-56798-9

## 関連項目
* DOS (オペレーティングシステム)
** MS-DOS
* Microsoft Windows
* DOSエクステンダ
* DOS Protected Mode Interface (DPMI)
* Virtual Control Program Interface (VCPI)
* Extended Memory Specification (XMS)
* バンク切り換え