IBMメインフレームのOSやユーティリティーなどがプログラムの復帰コードを4の倍数にしているのは機械命令の仕様から来ています。なぜ4の倍数なのかは、呼び出したプログラムから戻った後の処理を行う復帰コード別ルーチンにジャンプするための分岐命令(GOTOする命令)の長さが4バイトだからです。
アセンブラー・プログラムにおいて、外部ルーチンの処理結果である復帰コードに応じて、復帰コードAの時は処理A、復帰コードBの時は処理B、復帰コードCの時は処理Cに分岐(GOTO)したいといった場合、いちいち IF RETCD=A THEN GOTO PROC-A のように復帰コード別に IF THEN に相当する比較と分岐の命令を書いていては効率が悪いので、復帰コードが何種類もある時は、アセンブラーでは復帰コード別処理ルーチンへ分岐するための分岐命令テーブルを作ります。飛び先を名前で指定する分岐命令は長さ4バイトなので、復帰コードが4の倍数だと1番目のテーブル・エントリー、2番目のテーブル・エントリーを復帰コードに応じて示しやすいからです。アセンブラー・プログラムにおいて復帰コード別の処理ルーチンに分岐し易いプログラムコードを書くためのよく言えば工夫、悪く言えばプログラマーの都合です。具体的には下記のようなコードを書きます。
1 2 3 4 5 |
CALL PROG1 CALL PROGRAM-1 外部ルーチンの呼び出し B *+4(R15) BRANCH BY RETURN CODE ブランチ・テーブルを使って復帰コード別に分岐するための命令 B RC0PROC RC=0, DO RC0PROC ブランチ・テーブルの1番目 B RC4PROC RC=4, DO RC4PROC ブランチ・テーブルの2番目 B RC8PROC RC=8, DO RC8PROC ブランチ・テーブルの3番目 |
個々の命令の個別の説明は省きますが、上記の5つの命令の中の2番目から5番目の「B」というのが分岐を行うBranch命令ですが、上の例のようにB命令を並べたもの(3番目から5番目の部分)をブランチ・テーブルと呼び、復帰コード(呼び出されたプログラムがレジスターR15に入れて通知する)をインデックス値にして分岐を行うために作られます。RETCD=0ならテーブルの先頭から0番地、RETCD=4ならテーブルの先頭から+4番地、RETCD=8ならテーブルの先頭から+8番地にそれぞれ格納された命令を直接実行するための命令テーブルです。
アセンブラー・プログラムの機械命令ではわかりにくいので、一般的なプログラム言語っぽい命令に置き換えると、
1 2 3 4 5 |
CALL EXTERNAL-ROUTIN. IF RETCD=0 THEN GOTO RET00-PROC. IF RETCD=4 THEN GOTO RET04-PROC. IF RETCD=8 THEN GOTO RET08-PROC. (RETCDが8だと3回目のIFでやっと引っかかる) |
のように書くのではなく
1 2 3 4 5 6 7 8 |
CALL EXTERNAL-ROUTIN. BGN-TABLE BRANCH BY RETCD. GOTO RET00-PROC. GOTO RET04-PROC. GOTO RET08-PROC. END-TABLE (RETCDに応じたGOTO命令が自動的に選択され実行される) |
のように書くと、復帰コードに応じた飛び先に、上から順に条件判定しなくても1回の条件判定で自動的にGOTOできる書き方がアセンブラーのプログラミング手法としてあります。
BGN-TABLEは、説明しやすくするための架空の命令で、中のテーブル・エントリーを使用してRETCD別のGOTO命令を実行しなさいという意味です。BGN-TABLEとEND-TABLE内のGOTO命令が1つの命令で、それぞれ4バイトの長さでメモリー上に書き込まれるため、復帰コードが4の倍数だと都合がよいのです。OSもユーティリティーもこのようなことから復帰コードを4の倍数にする設計がなされた、という背景がIBMメインフレームにあります。
0から順番に0、1、2、3のように復帰コードを割り当てた場合、ブランチ・テーブルを使うためにはどのプログラムにおいても4の倍数に変換するため、復帰コードを2ビット左にシフトするような処理が必要になりますが、それなら最初から復帰コードを4の倍数にすれば、各プログラムでいちいち4の倍数変換する必要は無くなります。たかが1命令と思うかも知れませんが、CPU能力もメモリーサイズも小さかった当時のコンピューター・システムでは、たかが1命令たかが数バイトでも無駄には出来ませんでした。