EXEフォーマット

EXEフォーマット（エグゼフォーマット）とはMS-DOSおよびその互換・後継であるWindowsの実行ファイルを格納するファイルフォーマットである。EXE は"executable"の省略形であり、Windowsプログラムの標準的なファイル拡張子である。多くのWindowsユーザーにとって、EXEファイルはWindowsプログラムと同義で".exe"は最も認知されている拡張子のひとつである。 ファイルの先頭には0x5A4D（ASCIIコードで'MZ'という文字列）のマジックナンバーが入っている。これは、MS-DOS 2.0の開発責任者の一人、Mark Zbikowskiのイニシャルに由来する。 .exeの拡張子を持つファイルのファイルフォーマットにはいくつかの種類が存在する。拡張ヘッダにより、WindowsやOS/2の実行ファイルの情報を指定し、これらのOS用に作られたプログラムが本来のアーキテクチャでOSで実行された場合は、その拡張ヘッダを解釈し、MS-DOS上で実行された場合、実行できない事を表示し終了させる等のプログラムを置くことが可能である。このようなフォーマットにはPortable Executable (PE) やNew Executable (NE), Linear Executable (LE, LX) 等が存在する。 16ビット DOS MZ executable 元々の DOS 実行ファイルフォーマットである。ファイルの先頭にはASCIIコードで "MZ" の文字があり、これで識別できる。 16ビット New Executable マルチタスクのMS-DOS 4.0で導入され、16 ビットの OS/2 と Windows で使われた。NEはASCIIコードの"NE"で識別できる。 32ビット Linear Executable OS/2 2.0で導入され、ASCIIコードの "LX" で識別できる。OS/2 2.0 と後継でのみ実行可能。 また、DOSエクステンダの一部でも利用された。 16/32ビット混在 Linear Executable OS/2 2.0で導入され、ASCIIコードの "LE" で識別できる。このフォーマットはWindows 3.x、OS/2、Windows 9xのVxDドライバとして使われた。また、DOSエクステンダの一部でも利用された。 16ビットと32ビットのWindows実行ファイルがWindows上で実行されるとき、NEまたはPEから実行が開始され、DOSスタブと呼ばれるMZコードは無視される。DOSではスタブは"This program cannot be run in DOS mode"、もしくは同様のメッセージを終了前に表示するためファットバイナリの最小フォームを形成している。レジストリエディタや古い WinZIP 自己解凍形式ファイル等のいくつかのデュアルモード(MZ-NE または MZ-PE)のプログラムにはより多くのDOSプログラムが含まれていた。 32ビット Portable Executable Windows NTで導入され、ASCIIコードの "PE" で特定できる。(ただし、ファイルの先頭はPEではなく"MZ"である) 64ビット Portable Executable (PE32+) 64ビットバージョンのWindowsで導入され、より多くのフィールドを持つPEファイルである。多くの場合、コードは32ビットか64ビットかのいずれかのPEファイルとして動作する。 また、上記のほかにも多くの特殊なEXEフォーマットが存在する。Microsoft Windows 3.xの386エンハンスドモードのカーネルであるWIN386.EXEや、Microsoft Windows 95等のカーネルであるVMM386.VXDでは特殊な拡張ヘッダで内部に存在するプロテクトモードのカーネルコードや仮想デバイスドライバ等へのオフセットを保持しており、リアルモードでの初期化を普通のDOSプログラムとして行った上で、そのヘッダにあるプロテクトモードのコードを実行していた。（WIN386.EXEではW3, VMM386.VXDではW4という識別子。W3 (LEファイルのコレクションでWIN386.EXEのみで利用された)とW4 (LEファイルの圧縮されたコレクションでVMM32.VXDのみで利用された)のほかにも DL、MP、P2、P3 (最後の3つはPhar Lap DOSエクステンダで使われていた)が存在していた。 MS-DOSで実行可能なバイナリのフォーマットには他に、COMフォーマットと言うファイルフォーマットが存在する。COMフォーマットは、コード、データ、スタックの全てのセグメントが同一であるモデルで、開始番地も固定の0x100であるメモリイメージそのものであり、シンボル再配置も無い。COMフォーマットは、ファイルヘッダを持たず拡張性がなかった。これに対し、EXEフォーマットは連続した一つのメモリイメージで、コード、データ、スタックの全てが別々の複数のセグメントを用いてアクセスする必要のある場合に対応し、開始アドレスおよびその時のセグメントレジスタの値をファイル先頭から相対指定することが可能でセグメント指定の再配置エントリが存在する。 C言語による表記は以下の通りである。尚、この定義はWineで使われているヘッダファイル (winnt.h) の定義から引用した。WORDは16ビット整数であり、DWORDは32ビット整数である。 typedef struct _IMAGE_DOS_HEADER { WORD e_magic; /* 00: MZ Header signature */ WORD e_cblp; /* 02: Bytes on last page of file */ WORD e_cp; /* 04: Pages in file */ WORD e_crlc; /* 06: Relocations */ WORD e_cparhdr; /* 08: Size of header in paragraphs */ WORD e_minalloc; /* 0a: Minimum extra paragraphs needed */ WORD e_maxalloc; /* 0c: Maximum extra paragraphs needed */ WORD e_ss; /* 0e: Initial (relative) SS value */ WORD e_sp; /* 10: Initial SP value */ WORD e_csum; /* 12: Checksum */ WORD e_ip; /* 14: Initial IP value */ WORD e_cs; /* 16: Initial (relative) CS value */ WORD e_lfarlc; /* 18: File address of relocation table */ WORD e_ovno; /* 1a: Overlay number */ WORD e_res[4]; /* 1c: Reserved words */ WORD e_oemid; /* 24: OEM identifier (for e_oeminfo) */ WORD e_oeminfo; /* 26: OEM information; e_oemid specific */ WORD e_res2[10]; /* 28: Reserved words */ DWORD e_lfanew; /* 3c: Offset to extended header */ } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;