自作の MZ EXE 形式のプログラム中で int 21h (ah=48h) でメモリを確保しようとしたところ、空きがなく確保できないという現象に遭遇した。 デバッガでメモリを見てみると、COM 形式のプログラムを実行した時のように、プログラム起動直後に既に空きメモリを全部自身が占有している状態になっていた。 プログラムに必要なメモリの最も大きいアドレスを計算してメモリの再割り当てを行うコードを書く手もあったが、リンク時には各セグメントのサイズが分かっているのだから、その辺り何か良い感じにできるのではないかと思って調べてみた。

MZ EXE の起動時のメモリ確保は minimum allocation と maximum allocation の値に従って以下のように行われるのがわかった。 これらの値はそれぞれ MZ ヘッダのオフセット 0ah と 0ch にある。

  • minimum allocation はプログラムを実行するのに最低限必要なパラグラフ数で、空きメモリがこれと比べて足りない場合にはプログラムはロードされない。
  • maximum allocation はプログラムが希望するパラグラフ数で、空きメモリがこれと比べて足りなくても最も大きい空きメモリのある空間にプログラムがロードされる。

以上より、maximum allocation を minimum allocation の値で上書きすれば、MZ EXE 実行時に minimum allocation のパラグラフ数のメモリしか確保されなくなる筈である。 ということで、上書き処理を行うプログラムを書いてみた。 → maxalloc.cpp

これを使って maximum allocation が minimum allocation と等しくなるように MZ EXE ファイルを加工したところ、無事プログラム起動時に占有するメモリが少なくなった。 めでたしめでたし。