最近は、DOSで遊んでいます。DOS-BOXではなくネイティブのPC-DOSS 2000です。
仕事で最初に使ったDOSは、PC-DOS 2.11でした。360KBのディスケット1枚に収まって いたように思います。HDDナシでも使用することができました。 また、コマンドも最低限度の物しかなく、バッチファイルを沢山作って対応したものです。 現在のPC-DOS 2000は、CD-ROMか11枚のディスケットからHDDにしかインストールできな くなっています。また、非常に多くの機能を含んでいます。ものすごい進歩です。
久しぶりにDOSをインストールし動かして昔を懐かしんでもつまらないので、 過去にいじってみて断念したPSP(プログラム・セグメント接頭部)を使ったコマンドラインの 引数や環境変数の取り込みモジュールを作成してみました。
Cでかくと、コマンドラインの引数はargcと*argv[]で、環境変数はgetenv()で、それぞれ 取得することができますが、PSPを使ってこれらの機能を実現してみたかったのです。もちろん アセンブラで書きます。
PSPは、DOSからアプリケーションに制御が移った時点のDSとESにPSPが配置されている セグメントアドレスが入っています。オフセットは0000Hです。このほかに、 DOSのファンクションコール62HでBXにセグメントアドレスを得る事ができます。 今回は、ファンクションコールを利用しました。
環境変数は、PSPのオフセット2CHから1ワードに環境変数が配置されている セグメントアドレスが入っていて、オフセット0000Hから環境変数が入っています。
コマンドラインの引数は、PSPのオフセット80Hにコマンドラインの文字数(コマンドの次の ブランクからおしりの0DHまで)が、コマンドラインの文字列がオフセット81Hからに入っています。 この領域は、省略時のディスク転送領域(DTA)も兼ねているので、ファイルを操作するプログラムでは 破壊されてしまいますので、要注意です。今回はモジュール内部にコピーを取っています。
コマンドラインの引数は、デリミタ文字(スペース、タブ、カンマ)で区切られており、 クオート文字(シングルクオートかダブルクオート)で始まる場合は次のクオート文字までを ひとまとめとして取り扱います。コンマでパラメータが始まっている場合、 最初の引数はヌルストリングと見なします。また、コンマが二つ続く場合はコンマの間に ヌルストリングがあると見なします。引数はとりあえず20まで扱えるようにしてありますが、 CONSTANT.INC中のMAXARGSを変更し再ビルドすることで、増減できます。引数一つあたり1ワード 消費します。
引数の例
abc "DEF ghijk" ---> [abc]、[DEF ghijk]の二つ ("["、"]"は目印の文字) , 123<TAB>567 ------> []、[123]、[567] (<TAB>はタブ文字) ABCDEF , , XYZ ----> [ABCDEF]、[]、[XYZ] XYZ "abc'def" ------> [XYZ]、[abc'def] abc 'def'ghi -------> [abc]、[def]、[ghi] xyz"abc<TAB>def ----> [xyz]、[abc<TAB>def]
作ってみたところ、マクロや定数を含めて約500行のプログラムができあがりました。 完成した物はenvaergs.zipです。
作り込んだのは、@getArgc,@getArgv,@getEnvの三つです。
@getArgcは、引数の個数を返します。
@getArgvは、指定された位置の引数を返します。
@getEnvは、指定された環境変数名の値を返します。
サンプルを2本作りました。
コマンドラインの引数を一行に一つづつ表示する"args.asm"。これは引数 を取得するサンプルです。引数の書き出しは目印に"["と"]"で囲んでいます。
もう一つのサンプルは、"printenv.asm"です。これは、引数で受け取った環境変数名を 探しだしその値を書き出します。変数名とその値は目印"["、"]"で囲んで表示します。
printenv.asmは以下の通りです。ちなみに関数の呼び出しは全てマクロでラップしてあります。 いかがでしょうか。
セコメントをする