ベースレジスターが足りないと嘆く前に
アセンブラーを覚えたての頃に多いと思うのですが、ある程度の規模や機能を持ったプログラムを作っている最中にベースレジスターが足りなくて困ったという経験をするかも知れません。1つのベースレジスターで4KB(ベースアドレス+変位0から4095バイト)の大きさをポイントできますが、プログラムにそれなりの機能を持たせると4KBや8KB程度のモジュールサイズに達してしまうことは珍しいことではありません。しかしS/370アーキテクチャーでは、モジュール間インターフェース、ワーク用、ベースレジスター用すべてを16個の汎用レジスターでまかなわねばなりません。特にベースレジスターは基本的に壊せないので最後まで予約されてしまうことになります。
レジスターが16個あってもベースレジスターとして使えるのは0番以外の15個、マクロも使わずサブルーチンも呼ばず、というプログラムならともかく、普通のプログラムならモジュール間インターフェース用に0、1、14、15番を使うのでこれらはベースレジスターには使いません。2番レジスターも命令によっては実行結果が格納されてしまうため除外、13番はレジスター退避領域のポインターに使う、すると3番から12番の10個しか残りません。10個全部をベースレジスターにしたら事実上プログラムは組むことは至難です。決まりはありませんが、1個で足りなければ2個多くて3個がベースレジスター個数としての一般的な指針でしょう。個人的には12番、11番の順で最大2個、非リエントラント・プログラムで3個(第1ベースに13番レジスターを使う)という決めごとを作っていました。
いずれにしても4つも5つもと半分近くのレジスターをベースレジスターに固定してしまうとプログラミングしにくくなるだけです。
必要があってプログラムが大きくなる場合、普通はモジュール分割を考えます。しかしこの場合は最初にきちんとしたプログラムデザインが必要です。プログラミングの途中でのモジュール分割はできなくはありませんがやりにくくなりますし予期せぬバグの元にもなります。分けるのなら機能や役割をきちんと考えた上できれいに分割する方が後々のメンテのためにもよいでしょう。
しかし作っている最中でどうしてもモジュールサイズが大きくなってしまうこともあります。あとちょっとでコーディングのゴールが見えているような場合は、今さら分割しなきゃだめかぁとも思うでしょう。そんな時は、プログラムで使っているデータ領域のポイントの方法を見直すと、意外な大きさの余裕を作ることもできます。参照するデータ領域が大きいほど効果があります。
比較的大きなデータ領域はベースの外に置く
RX形式アドレスでは変位は最大4095バイトしかありません。これがベースレジスターが参照できる範囲が4KBの元になります。2つのベースレジスターなら8KB、3つなら12KBとなるわけです。しかし命令と違ってデータ領域は必ずしもベースレジスターがポイントする範囲に置く必要はありません。命令実行時にそのデータ領域がアドレスできればいいのです。
MVC WORKAREA,BLANK CLEAR WORK AREA BY BLANK CHAR : : BLANK DC CL256' ' 256BYTE BLANK CONSTANT
一般的なコーディング。WORKAREAをブランク文字でクリアーする。この場合、BLANKというデータ領域の少なくとも先頭は、ベースレジスターでアクセスできる範囲に置かねばならない。これは次のように書き換えることもできる。
L R14,=A(BLANK) LOAD BLANK CHAR AREA ADDRESS MVC WORKAREA,0(R14) CLEAR WORK AREA BY BLANK CHAR : : LTORG , USER LITERAL PLACE AT HERE DROP , FORGET ALL BASE REGISTER BLANK DC CL256' ' 256BYTE BLANK CONSTANT
2番目の書き方では、MVC命令で直接BLANKという名前のデータ領域を参照せずに、一度レジスター14にBLANK領域のアドレスを読み込んでレジスター14番をアドレスポインターとしてMVC命令で使っています。つまりワンクッション置いて参照するコーディングです。このようにすると256バイトもの大きさを取るBLANKというデータ領域はベースの外に置かれても大丈夫です。命令自体が1つ増え、アドレス定数のリテラルも追加されるので、1番目の例のMVC命令1つに比べれば命令数で1つ、大きさでLOAD命令の4バイト、アドレス定数のリテラルで4バイトの計8バイトが増えますが、代わりに256バイトの領域を外へ出せるのでベースレジスターでアクセスできる余裕は差引248バイト増えます。こんなようにしてデータ領域へのアクセス方法を見直せば結構な大きさの余裕を作ることができるでしょう。数十バイトもの領域がいくつもあるなら百数十バイト程度の余裕を作り出すことは決してむずかしくありません。データセットのアクセスに使う領域などもベースの外に置いてもいいでしょう。レジスターでの参照が面倒ならDSECTにしてラベル参照すればいいのです。この方法ならロジックは変わりませんから、修正に伴うバグも出にくいでしょう。1番、14番、15番といったレジスターなら一時的な目的に使いやすいでしょう。筆者はこの方法に結構助けられましたが、それは最初に作るときよりは後になって機能を追加したりバージョンアップなどでのメンテナンスの時でした。こんな方法もある、と覚えておいて損はありません。
その他、バッチ処理プログラムなど、非リエントラント構造のプログラムなら第1ベースレジスターに13番を使い、12番、11番をそれぞれ第2、第3ベースレジスターに回す方法もあります。具体例はこの記事(GR13をベースレジスターに使う)を参照して下さい。13番レジスターをたった72バイトの退避領域のためだけに使うのももったいないことです。