ダンプ・リスト解析入門 ⑩:プログラム割込みによるABENDダンプ解析サンプル

一連の「ダンプ・リスト解析入門」シリーズの最後に、簡単なプログラムを使ってABENDダンプの解析を行います。アセンブラー・プログラムで起こりがちなS0C4 ABEND(記憶保護例外)です。故意にプログラムで0番地などに書き込むのは現実的ではないので、実践でもありがちな例で行ってみます。サンプル・プログラムの内容は、STCK命令で得たCPUの現時刻をYYYYMMDD HHMMSS形式に変換するものです。実際の変換にはMVSのAPIサービスであるCONVSTCKマクロを使用します。

サンプル・プログラムのABENDによるダンプ・リストとプログラムのアセンブル結果

ダンプ・リスト(SYSUDUMP)

アセンブリー・リスト

ダンプとアセンブリー・リストからエラーの箇所を見つける

まずは、ダンプ・リストからABEND時のPSWとレジスターの内容を確認します。徴候ダンプを見るのが早くて簡単です。

ABEND箇所はPSWが示す1つ前の命令なので、徴候ダンプなどに示された命令長(ILC 6)分前に戻すと、xD20FE000100Cがその命令となる。この場所は、x7FD6-x7F18=xBEなのでプログラムの範囲内であることがわかる。

PSWが示すABENDアドレスはx7FD6、プログラムのベース・アドレスはx7F18であることがわかります。x7FD6はプログラムの先頭からのオフセットxBEの位置です。PSWは次の命令を指すので、実際にABENDしたのは1つ前の命令です。ILC(命令長)が示す値を引くとxB8で、これがABENDした命令の位置です。アセンブリー・リストからこれがMVC命令であることがわかります。この命令は、GR1が示すアドレスのオフセット12の位置のメモリーの内容をGR14が示すアドレスにコピーするものです。

GR1とGR14の内容を確認すると、GR1はプログラム内で問題なさそうですが、GR14には6が入っています。つまり、アドレス6番地に書き込もうとしています。そのため、記憶保護例外S0C4 ABENDとなったようです。
では、何故コピー先のアドレスを示すGR14に、6という誤った値が入ったのかを引き続き追求します。そのためには、アセンブリー・リストでこの命令よりさらに前の命令列を確認します。

アセンブリー・リストを見ると、オフセットxB4のLAE命令でR6というラベルのアドレスがGR14にセットされています。ラベル名R6?って何でしょうか。実は、ここはマクロ命令による展開命令列です。実際に自分でソース・プログラム上に書いた命令ではありません。マクロ命令による展開命令列かどうかは命令の左側の通し番号の直後の+マークの有無でわかります。このABENDで問題となっているLAE命令にもMVC命令にも+マークが付いているのでマクロ命令による展開命令列であることがわかります。命令列をリスト上で上方向にさかのぼれば展開したマクロ命令がわかります。これはプログラマーがソース・プログラム上に書いたものです。

問題となっている命令列を展開したのはSTCKCONVマクロであることがわかります。一見すると問題なさそうですが、パラメーターをよく見てみるとCONVVALパラメーターに値として「R6」が指定されています。これがLAE命令でのラベル名R6に関係があるようです。
STCKCONVマクロの直前でGR6にEDITAREAのアドレスをロードしていますから、CONVVALパラメーターではGR6に格納されたアドレスの領域を指定したものですが、値の表記が誤っているため、マクロ内でR6をレジスター番号ではなくラベル名として処理されてしまったものです。正しくは次のようにマクロ命令を書かなければなりません。

マクロ命令のパラメーターの値にレジスターの内容を指定する場合は、レジスター番号を()でくくって記述するのが一般的です。この事は各マクロのマニュアルでも明記されています。ソース・プログラムだけを追っているとわかりにくいバグの例でもあります。正しく記述されたSTCKCONVマクロの展開は次のようになります。

エラーの原因となったLAE命令では、R6ではなく0(0,R6)の表記に変わり、6番地ではなくレジスター6番の内容をベースにしたアドレスがGR14にロードされることになりプログラムは意図した通りに正しく実行されます。

サンプル・プログラムのソースコード