ダンプの採取とフォーマット

By kamii - Last updated: 木曜日, 11月 6, 2008

ダンプとはプログラムおよびプログラムが使用しているメモリー上のデータを、診断のためにデータセットに書き出したものです。プログラムが動いているジョブのアドレス空間のメモリー内容が出力されます。
MVSではプログラムが異常終了した時や、固まって動かなくなってしまった時(WAITやLOOP)はメモリーダンプを採って、そのダンプリストを基に異常の原因を調査することがよく行われます。アプリケーションの場合は使用する言語プログラム(COBOLやPL/Iなど)のデバッグ機能や、トランザクション処理システム(CICSやIMS)が提供する診断機能などを使いますが、アセンブラー言語で作成されたプログラムやミドルウェア製品自体に異常が起きた場合、ダンプは原因究明の重要な調査資料になります。


SYSUDUMPとSYSABEND

MVSではダンプは基本的な診断資料なので、特別な操作をしなくても必要なときに自動的に書かれます。
JCLにSYSUDUMP DD文またはSYSABEND DD文を定義すれば、プログラムが異常終了した時やCANCELコマンドでダンプの出力が指定された時に、MVSによってDD文に指定されたデータセットに出力されます。通常は出力先としてSYSOUTが指定されることが多いでしょう。

SYSUDUMPとSYSABENDには本質的な違いはなく、ダンプを採る範囲の違いによって使い分けられます。それぞれがどの範囲をダンプするかはMVSのパラメーターに定義されます。多くのユーザーではSYSUDUMPはユーザーアプリケーション用、SYSABENDはシステムプログラム用として使い分けられます。

予めダンプ出力用データセットを作成しておく場合は、PSデータセットとして容量のみを指定します。RECFM、ブロック長、レコード長はMVSがダンプ出力時に設定し直します。



システムダンプ(SVCダンプ)

システムダンプはSVCダンプとも呼ばれ、プログラムの異常終了ではなく、オペレーターがコマンドによって採取するダンプです。アドレス空間内の仮想記憶域の内容を書き出すので、アドレス空間ダンプとも呼ばれます。ダンプデータは予めシステムに定義したダンプ・データセット(SYS1.DUMPnn)に出力されます。SYSUDUMP、SYSABENDと違ってバイナリー形式のままなので解析には専用のユーティリティを使ってフォーマットします。OSのモジュールも異常を検知した場合などに、自らこの形式のダンプを出力します。
一般のプログラムでは通常使われませんが、ミドルウェアやISV製品などでは診断資料としてよく利用されます。特にWAITやLOOPなど、プログラムが正しく動けずに止まってしまっているような状態では、アドレス空間ダンプはエラーの状態のままメモリー内容がダンプされるため、より正確な診断が可能になります。

通常はRGNでリージョン全域を採れば十分ですが、必要に応じてCSAやLPA域を追加します。データベースのように複数の空間からのサービスを受けるようなプログラムではCSAやSQAなども必要となる場合があります。

DUMPコマンドを使用する前に、D DUMPコマンドで空きのダンプデータセットがあるかを確認します。必要ならばDD CLEAR,DSN=nnコマンドで使用済みダンプデータセットをクリアーします。(MSPとVOS3ではユーティリティによるクリアーが必要)




関連マニュアル

Filed in ありがたいサンプルJCL, システムプログラマーのための手引きいろいろ

05.REXX 制御文

By takao - Last updated: 木曜日, 11月 6, 2008

DO, END

Cなどで{}で囲むところをREXXではDO ENDで囲みます。不正確さを承知の上で簡単に説明すると、DO ENDで囲むことで複数の命令が一塊りとして扱われます。
DO
VAR1 = “HELLO”
VAR2 = “WORLD”
say VAR1 VAR2
END

IFと条件式の評価

IF文などはなにかのプログラミング言語を知っている人ならば、例を見たら説明は必要ないと思います。

IF VARIABLE = 0 THEN
SAY “zero”
ELSE
SAY “non zero”

ただ、IF文やループでは必ず「条件式の評価」というのが必要です。
比較演算子は以下のものがあります。
>, <, >=, <=, = これらはおなじみでしょうが、
<> が等しくない(not equol)です。

Do ループ

条件式でのループの例です。

NUMが3より小さい間、繰り返す。
NUM = 0
DO WHILE NUM < 3
SAY "small"
END

条件になるまで、繰り返す。(WHILEとの違いは必ず一度は行われる)
NUM = 4
DO UNTIL NUM >3
SAY “LARG”
END

決まった回数繰り返す
DO 5
SAY “hello”
END

変数をコントロールしながら繰り返す
DO I=1 to 100 BY 2
SAY I
END

ループから途中で抜けたい場合には、LEAVEか、ITERATEを使います。
LEAVEは、もっとも内側のDO ENDを終了してしまいます。ITERATEは、もっとも内側のDO END内をDOに戻って行います。

LEAVEの例:
DO 4
say “—–”
DO 3
SAY “test”
LEAVE
END
END

結果:
—–
test
—–
test
—–
test
—–
test

ITERATEの例
DO 5
SAY “—–”
DO 10
SAY “test”
ITERATE
END
END

結果:
—–
test
test
test
—–
test
test
test
—–
test
test
test
test
—–
test
test
test

SELECT, WHEN, OTHERWISE, END

REXXのSELECT文は、あまり便利とはいえません。以下のように違う条件を書け、わかりにくくなる可能性があります。

VAR1 = “blue”
VAR2 = “yellow”
SELECT
WHEN VAR1 = “blue” THEN SAY “blue”
WHEN VAR2 = “red” THEN SAY “red”
WHEN VAR2 = “yellow” THEN SAY “yellow”
OTHERWISE
SAY “white”
END

NOP

なにもしない命令です。こういう時に使います。
IF A=B THEN
NOP
ELSE
SAY “not qual”

以上で制御系はおわりです。
Filed in REXX入門

05.リンケージ規約(サブルーチンを作る)

By kamii - Last updated: 木曜日, 11月 6, 2008

リンケージ規約(Linkage convention)とはプログラム間の呼び出しに関する取り決めです。規模の大きいプログラムはいくつかのモジュールに分割して、異なる人によって作成されたりします。各人が好き勝手に作っては上手く動きません。そこでプログラム間のインタフェースに共通のルールを作ります。
MVSでもプログラム間のインタフェースに関して標準的な約束事を取り決めています。MVSで動作するプログラムはこの約束事に従って作ることが重要ですし、知っていなければ(守らなければ)正しく動くプログラムを作ることができません。タイトルには(サブルーチンを作る)とありますが、メインルーチンを作る場合でも同じ事です。アプリケーションとしてはメインルーチンであっても、MVSからは一種のサブルーチンとして扱われるのです。なおリンケージ規約はアーキテクチャーで定められたものではなく、使用するオペレーティング・システムによって取り決められます。MVSやVSE(MSP,VOS3,XSPも)などIBMメインフレーム系アーキテクチャーで動くOSは基本的に同じリンケージ規約が使われています。アプリケーションのみならず言語処理プログラムやユーティリティなどもリンケージ規約に従って作られています。OSや多くのミドルウェアなどもユーザープログラムに制御を渡す(呼び出す)際はリンケージ規約を守ります。

リンケージ規約が取り決めているのは以下のプログラム間インタフェースです。


MVSのリンケージ規約

リンケージ規約で使用するGR0,1およびGR13,14,15の各レジスターはリンケージレジスターとも呼ばれます。これらのレジスターはプログラム間リンケージで重要な役割を果たすため、壊してはならないと後生大事に抱えているビギナー・プログラマーをたまに見かけますが、プログラムの冒頭で保管域にセーブしているのですから自由に使ってかまいません。それにMVSやDFPのサービスを呼び出せばどうせ壊れます。レジスター13以外の0,1,14,15番レジスターは作業用のワーキング・レジスターです。積極的に使いましょう。


プログラムの入口点処理と呼び出し元への復帰処理のサンプル

このプログラムはEXEC文のPARMパラメーターで指定されたパラメーター文字列を、コンソールに表示する簡単なプログラムです。
必要な初期設定を行った後、BAS 10,SHOWPARM命令でSHOWPARMサブルーチンを呼び出してパラメーターをコンソールに表示し、復帰コード0を設定して呼び出し元(MVSのジョブ管理ルーチン)に戻ります。
CSECTアセンブラー命令以下、⑥までの処理がリンケージ規約に基づく最初のセットアップ処理です。ハウスキーピング処理とも呼ばれます。何種類かの方法がありますが、リンケージ規約に合っていれば、使う命令や順序などに決まりはありません。⑧以降は呼び出し元への復帰処理ですが、これも重要なのは、レジスターを呼び出された時の状態に復元する、と言うことです。レジスターを元に戻さずに復帰してしまうと、呼び出し元は正しく処理を継続できません。

リンケージ規約によるハウスキーピングの処理には複雑な命令は必要ありません。「マシン命令入門」で紹介した基本となる何種類かの命令でロジックが作れます。プログラムの規模や内容に関係なく、とにかく絶対必要な処理なのでしっかりと覚えて下さい。
ここまでくれば、実際にMVSで動かすプログラムを書き始めることができます。まだ使ってない命令やOSのサービスAPIなどたくさんありますが、残りは必要に応じて調べて行けばいいのです。次回からは計算や文字処理、分岐とループなどプログラミングっぽいテーマで解説します。

Filed in S/370アセンブラー講座

04.REXX お約束ごとと命令群

By takao - Last updated: 水曜日, 11月 5, 2008

変数とリテラル

REXXの変数は独特です。変数名は英字で始めます。続く文字は数字か、_です。 大文字小文字の区別はありません。そして、VARIABLEと最初に変数名を書くと、その値も”VARIABLE”です。もちろん、他の言語と同様に代入式で値を変更できます。
VARIABLE = “hoge”
変数に型はありません。すべてが文字列だと思ってください。特定の演算時に、型変換されます。

リテラル(特定の値)は、” か、 ‘ で囲みます。エスケープしたい時は、二回続けます。
VARIABLE = “He is “”strong”"”

最後に文字で表せない場合、16進数表記や2進数表記が可能です。

VARIABLE = ’0d0a’x /* おなじみ、CRLF */
VARIABLE = ’0000 1101 0000 1010′b

配列

変数に.をつけると配列として扱われます。
ARRAY.1 = “asa”
ここでARRAYの部分を「幹(ステム)」と呼びます。これだけを指定すると、配列全体を意味します。
ARRAY. = 0

もちろん、添え字部分は変数が許されます。
I = 1
say ARRAY.I
添え字は、データは1から始まります。0には、配列の大きさが入ります。したがって配列を扱うループは次のように書きます。

DO I=1 TO ARRAY.0
say ARRAY.I
END

ラベル

関数の名前や、GOTO相当のSIGNAL命令でジャンプする先などにつけます。決めた名前の後ろに : をつけます。

say add(1,2)
exit

add: procedure
parse arg a,b
return a + b

改行が命令の切れ目です。続けたいときは , を最後につけます。
VARIABLE = ,
“hoge”

逆に一行に複数の命令を書きたいときは、 ; で区切ります。
VARIABLE = “hoge” ; say VARIABLE

プログラム中のコメントは、
/* */ 中に書きます。これは、改行しても有効です。
/*

*/

命令群

ARG, CALL, DO, DROP, END, EXIT, IF, INTERPRET, ITERATE, LEAVE, NOP, NUMERIC, OPTIONS, PARSE, PROCEDURE, PULL, PUSH, QUEUE, RETURN, SAY, SELECT, SIGNAL, TRACE
の23個くらいしかありません。
Filed in REXX入門

IMS FastPath

By takao - Last updated: 水曜日, 11月 5, 2008
IBMのデータベース管理システムにIMS Fast pathというものがあります。これは、日本の大手銀行や大手製鉄所の要求により、最初は作られました。従来のIMSと違い、パフォーマンスを追及した製品です。現在、次のような特徴をFast Pathはもっているといわれています。
これらは、もちろん犠牲もあります。複雑なデータベース構造はできない。データベースレコードの場所を決めるランダマイザー(ハッシュ)を作らねばならない、トランザクションのアトミックが荒い、などなど。大量のトランザクションを処理するという至上命題のため、開発、運用側にしわ寄せがくるのは仕方がないことかも知れません。

この図は、IMS FastPathのシステム概念を表しています。通常のIMSはメッセージキューというデータベースにメッセージが格納されますが、Fast Pathはコントロールリージョン内にある、EMH(Expedited Message Handler)といわれるメッセージルーティングにより、即座に処理リージョンに渡されます。ある程度のキューはもっていますが、あまり滞留はしません。リージョンが即座に処理できるのは、特定のトランザクションコードに応じたプログラムをあらかじめ、ローディングしているからです。(少し厳密にいうと、Load Balancing Groupにふりわけられ、空いているFPリージョンに渡される)
この常駐していて、トランザクションを即座に処理する動作をWait for Inputといいます。
DBRCはリスタートリカバリーをつかさどるため、IMSのシステムの状況をすべてRECONというデータセットに書き込んでいます。IRLMはデータベースのロック情報を保持しています。データベースをシステム同士で共有する場合はロック情報がやりとりされます。
IMS用語で、メッセージが入ってくることをエンキューといい、出て行くことをデキューといいます。MVSのENQ,DEQと混同しないようにしましょう。
データベースはDEDBというVSAM ESDSを利用しながらも、早いアクセスを実現したDBMSです。これは、VSAM Media Managerを使い論理レコード(CI)の単位でアクセスするため、CIの集まりをUnit of Work(UOW)という概念でまとめ、一度にアクセスできる大きさをあらかじめ決めてあります。オーバーフロー域はあらかじめ決められており、independent Overflow域をあふれてしまうとトランザクションはエラーで返されるため、常に監視が必要です。

ログも通常IMSと違うログレコードNo.をもっています。Fast Pathに比べた普通のIMSをFull Function IMSといいます。両方をひとつのシステムで使うことも可能なのですが、Fast Pathを生かすために、あまり混在では使わないようです。
Filed in メインフレーム・ソフトウェア

04.S/370マシン命令入門

By kamii - Last updated: 火曜日, 11月 4, 2008

アセンブラー言語におけるプログラムの書式と基本的なアセンブラー命令が理解できるとプログラムを書く準備が整います。しかしアセンブラー言語ではCPUに直接指示を与えるため、プログラムを書くためにはCPUと関連するハードウェアに関する知識がどうしても必要です。ここではアセンブラー・プログラミングに関するCPUのしくみや実際にCPUを動かすためのマシン命令の基礎について解説します。


CPUとPSW

S/360、S/370以降ESA/390および互換アーキテクチャーではCPUは32ビットCPUです。命令セットはIBM社独自のものが採用されています。この講座では現在のzアーキテクチャーの前身である32ビットCPU命令を中心に解説します。zアーキテクチャーではCPUは64ビットになり命令セットも大幅に拡張されましたが従来のアーキテクチャーでサポートされている命令セットはそのまま使用できます。

PSW(Program Status Word)はプログラム状態語と呼ばれ、CPUで現在動いているプログラムの走行状態(実行状況)を示す64ビットの特殊なレジスターで、CPU動作を制御する基本的な情報が格納されています。最初からPSWすべての情報について覚える必要はなく、アセンブラー言語でプログラムを作る上で、デバッグ作業をする上で必要なものを最初に覚えればいいでしょう。PSWのフォーマット

PSWには「 078D0000 00006192 」こんな値が格納されていたりします。
PSWの後半32ビットが次に実行する命令の仮想アドレスを示します。32ビット目がアドレスモードでプログラムが24ビット・31ビットモードのどちらで動いているかを示します。ビットが1なら31ビットモードです。残りの31ビットに命令アドレスが入ります。今実行している命令ではなく、次に実行する命令のアドレスであることを覚えて下さい。後は2バイト目です。例ではx8Dとなっていますが、8が記憶保護キーでPSWキーと言います。PSWキーとメモリー上のキーが一致していれば書き込みができます。次のDが問題プログラム状態を示します。ここがCなら監視プログラム状態(スーパーバイザーモード)です。正確には他のビットとの組み合わせでDやCになるのですが、滅多なことでは他のパターンにはなりません。取りあえずはこれだけでいいでしょう。3バイト目の前半4ビットのうち、第2,3ビットが命令の結果を示す条件コードですが、実際PSWの条件コードを見てデバッグするようなことはあまりありません。


レジスター

CPUには16個の汎用レジスター(General Purpose Register)があります。GPRまたはGRと略され32ビットの長さを持ち、それぞれ番号(0?15)で識別されます。GPRは命令オペランドのアドレス計算、整数演算、論理演算、実行結果の格納などに用いられます。汎用レジスターの他にCPUの制御に使う制御レジスター、クロスメモリー機能で使用するアクセスレジスター、浮動小数点演算に使う浮動小数点レジスター(64ビット)があります。汎用レジスター以外は一般のプログラムでは基本的に使用しません。zアーキテクチャーではCPUに合わせて汎用レジスターと制御レジスターは64ビットに拡張されていますが、これまでの32ビットCPU命令を使う場合はその違いを意識する必要はありません。

レジスターのいちばん左端がビット0です、以降右へビット1,2,3と続き右端がビット31になります。※CPUが複数個実装されているマルチCPU構成のプロセッサーでは、レジスターは各々のCPU毎にあります。


主記憶装置(メモリー)へのアクセス

主記憶装置はプログラムとプログラムが使用するさまざなデータを格納します。S/370以降のアーキテクチャーでは仮想記憶システムなので、我々が作り動かすプログラムはすべて仮想記憶上で動作します。実記憶(リアルメモリー)を直接アクセスすることはありません。以降の解説も主記憶装置あるいはメモリーはすべて仮想記憶装置を指します。
主記憶には先頭からアドレス(番地)が振られ、バイト単位でアクセスできます。アドレスはx00000000から始まりx00FFFFFF(16MB)さらにx7FFFFFFF(2GB)へと続きます。


アドレッシング

メモリーをアクセスする命令は、オペランドで操作の対象となるデータがメモリー上のどこにあるかを指し示す必要があります。これがアドレス表現で、命令実行時に実際のメモリーアドレス(実効アドレス)が計算されます。CPU命令ではメモリー上のアドレスは基本的に以下の2つの方法でアドレスが計算されます。


ベース+変位

レジスターに格納されたベースアドレス(基底アドレス)の値に変位(displacement)を加えて主記憶アドレスを求めます。変位はベースアドレスから何バイト離れたところを示すかの数で0?+4095の値が使えます。変位は命令のオペランド中に固定値で示されます。ベースアドレスを格納したレジスターのことをベースレジスターと呼びます。この方式では4ビットでベースレジスター番号、12ビットで変位を示し、アドレス部の命令オペランドは16ビットとなります。
ベースレジスターにx6000が入っていて命令オペランドで変位がx128(296)となっていれば、主記憶アドレスはx6128となります。

「STCK 120(12)」 ベース+変位方式はオペランドをこのように表現します。書式は変位(ベースレジスター番号)です。12番レジスターの内容に120を加えた数がアドレスになります。人間がいちいち変位を計算するのは面倒なので、普通は変位(ベースレジスター番号)を直接書くよりはラベル名で示します。
「STCK AREA」 のようにオペランドにラベル名が書かれた命令はアセンブラーによって STCK 120(12) と翻訳されます。命令を翻訳する時、どれをベースレジスターに使うかはUSING命令で決まります。USING LABELA,8とすれば、LABELAがベースアドレスでベースレジスターが8番です。USING *,12とすれば、USING命令を書いた場所がベースアドレスでベースレジスターは12番となります。基本的にプログラムは最低でも1つのベースレジスターを使います。通常はプログラムの先頭をベースアドレスにします。ベースレジスターは0以外であればどのレジスターでもいいのですが、1,2,13,14,15は避け3?12番の中から選びます。どれを使うかは最初に習ったり、手本にしたりしたプログラムのスタイルで決まることが多いようです。
アセンブラーはUSING命令で指定したベースレジスターを使って命令を翻訳しますが、指定されたレジスターにベースアドレス値を設定することまではしません。アセンブラー命令とCPU命令の違いがわかっていないとこう勘違いしてしまうかも知れません。アセンブラーのUSINGは命令オペランドをラベル名で書けるようにするだけです。USING命令で指定したベースレジスターに正しいベースアドレス値を設定するのはプログラマーの仕事で、どのプログラムも最初にこれを行います。


ベース+インデックス+変位

ベース+変位のアドレス計算にさらにインデックスアドレスを加えたものです。
レジスターに格納されたベースアドレス(基底アドレス)とインデックスアドレスの値に変位(displacement)を加えて主記憶アドレスを求めます。変位はベース+インデックスアドレスから何バイト離れたところを示すかの数で0?+4095の値が使えます。変位は命令のオペランド中に固定値で示されます。インデックスアドレスを格納したレジスターのことをインデックスレジスターと呼びます。この方式では4ビットでインデックスレジスター番号、4ビットでベースレジスター番号、12ビットで変位を示し、アドレス部の命令オペランドは20ビットとなります。
ベースレジスターにx6000が、インデックスレジスターにx2000が入っていて命令オペランドで変位がx128(296)となっていれば、主記憶アドレスはx8128となります。

「LA R1,120(10,12)」 インデックス+ベース+変位方式はオペランドをこのように表現します。書式は変位(インデックスレジスター番号,ベースレジスター番号)です。10番および12番レジスターの内容に120を加えた数がアドレスになります。
アセンブラーではラベル名のみでオペランドを指定した場合、インデックスレジスターは使用されません。インデックスレジスターを使うには「LA R1,AREA(10)」のようにインデックスレジスターを使用することを明示する必要があります。

インデックスレジスターはすべての命令で使えるわけではなく使用できる命令が決まっています。またベース+インデックス+変位方式の命令でもインデックスレジスターの使用は任意で、使わずにベース+変位でのみアドレス計算をするなら、インデックスレジスター番号に0を指定します。(あるいは省略)
S/370ではレジスター0番はベースレジスター、インデックスレジスターどちらとしても使用することはできません。オペランドで指定した0は0番レジスターではなく、数としての0そのものを意味します。「STCK 120(0)」「LA R1,120(0,0)」はいずれも主記憶アドレス120番地を指します。これはとても重要なことなのでよく覚えておいて下さい。

マシン命令における主記憶のアドレッシング

マシン命令における主記憶のアドレッシング


S/360やS/370アーキテクチャーにおける命令のオペランド・アドレスはプログラム内に直接持たれない、間接アドレッシング方式です。ベースレジスターの値を変えることで、プログラムを例えば主記憶の5000番地、10000番地あるいは32080番地など、主記憶のどこにでも配置できるようになります。これによってプログラムはリロケータブル(再配置可能)な性質を持つことが出来ます。仮想記憶システムが登場する以前の、実記憶上でプログラムを直接動かしていた時代では大きなアドバンテージでした。実効アドレスを求めるためのアドレス表現が複雑に見えますが、実記憶装置をいかに効率よく使い、いかに少ない長さでオペランドを表現するかと言うことで考え抜かれた設計なのです。


アドレッシングモード

レジスターは32ビットなのでフルビット使えば実効アドレスの範囲はは0?4GB-1となりますが、S/360システムでは下位24ビット(3バイト)を主記憶アドレスに使用しました。24ビットでは0?16MB-1です。当時のメモリー容量は数十?数百KB、大きくても数MBでしたから、32ビット全部をアドレスに使うよりは、1部を他の目的に使おうと言う発想は自然でした。S/370システムでも24ビットアドレスはそのまま踏襲され仮想記憶も16MBの大きさを持ちました。基本的にプログラムはx00000000?x00FFFFFFの範囲でしか主記憶をアクセスできません。これが24ビット・アドレッシングモードです。先頭の1バイトは主記憶アドレスとしては無視されるため、メモリー容量が小さかった当時はメモリーを節約するために、この部分にさまざまな制御用の情報をフラグバイトとして持ちました。4バイトあればXL1′フラグ’+AL3(アドレス)として使われることも多く、MVSでは今でも随所にこのパターンが残っています。

さすがに主記憶容量が16MBではどうにもならなくなったため、仮想記憶の大きさは31ビットで表現できる2GBに拡張されました。32ビットにしなかったのは24ビットモード・プログラムに対する互換性のためです。32ビットのうち、先頭ビットをアドレスモードの判定用に用い、残りの31ビットを主記憶アドレスに使いました。この場合プログラムはx00000000?x7FFFFFFFの範囲で主記憶をアクセスできます。これが31ビット・アドレッシングモードです。PSWのアドレス部(後半32ビット)の先頭ビットが0であれば24ビットモード、1であれば31ビットモードとなります。
x00006000 → 24ビットモード
x80006000 → 31ビットモード

特別に指定しない限り、アセンブラー言語で作成したプログラムは24ビット・アドレッシングモードのプログラムになります。まずは基本となるこのモードでプログラミングを覚え、それから31ビット・アドレッシングモードへ進む方がいいでしょう。もし新しいアプリケーションをこれからアセンブラー言語で作るなら最初から31ビットモード(あるいは64ビットモード)のプログラムで覚えてしまってもいいのですが、実戦でのアセンブラー言語はOSやパッケージソフトウェアの出口ルーチンを作ったり、過去に作られた古いプログラムの改良や他言語への書き換え、と言ったことに使われますから24ビット、31ビットの両方のアドレッシングモードを理解して必要に応じて使い分けられるようにすべきです。またそれは今後64ビット・アドレッシングモードを理解する上で必ず役に立つはずです。


境界調整

データや命令をメモリー上の整数倍アドレスから配置することを境界調整(バウンダリー合わせ)と言います。例えばフルワードの整数は4の倍数で始まるアドレス、ハーフワード整数は2の倍数で始まるアドレスにデータを揃えることです。DCやDS命令を使用して定義されたデータはアセンブラーが必要に応じて境界調整してくれます。
なお現在のCPUにはバイト式オペランド機構(byte oriented operand)が備わっているため、フルワード整数が2の倍数や奇数のアドレスで始まっていてもエラーにならずに実行されます。しかしきちんと境界調整がなされている場合に比べて若干のオーバーヘッドが生じます。ただし命令は必ずハーフワード境界に調整されていなければなりません。命令が奇数番地に置かれるとその命令を実行しようとした時に、プログラムは指定例外(S0C6)でABENDします。命令と命令の間にキャラクター型のデータを挟むような場合は特に注意が必要です。アセンブラーのDS 0HやCNOP命令で明示的に境界調整を行います。
とりあえずは実行命令の列の中でフルワード境界に調整する必要があるならCNOP 0,4、データ域の直後に命令を置く場合はDS 0Hと覚えておけばいいでしょう。特に命令についてはデータ領域の直後であろうがなかろうが、命令自身にラベルを付けるのではなく、直前にラベル付きのDS 0Hを置きます。普段からそういう癖をつけるとよいでしょう。CNOP命令の詳細はアセンブラーのマニュアルを参照して下さい。


命令の形式

CPU命令は2,4,6バイトのいずれかの長さを持ち、命令によってその長さが決まっています。オペランドの内容によって長さが変わることはありません。また命令には形式があって命令長やオペランドのフォーマットなどは形式によって定められています。同じ命令なら形式もオペランドの内容によって変わることはありません。現在のzアーキテクチャーでは命令セットが増えたため命令の形式も増え約20種類近くもあります。ここでは基本となる6つの命令形式を紹介します。

命令形式を知らなくてもアセンブラー言語でのプログラミングはできます。ただしデバッグ作業でダンプリストの解析をしたり、意図しない実行結果となった時に改めてアセンブルリストをトレースする際には命令形式の理解は必要になります。特にCPU命令のオペランドを間違った時、構文自体が正しければアセンブラーはエラーにしません。そのためソースプログラムだけを追っていては誤りに気づかないことは多いのです。命令形式がわかっていれば、マシンコードに翻訳されたCPU命令を見て、元のソースの命令記述の誤りに気づけるようになります。
命令形式を理解する早道はとにかくアセンブルリストを見ることです。翻訳されたマシンコードと自分が書いた命令を対比させて読む癖をつけます。デバッグには必ずアセンブルリストを使い、元のソースプログラムはプログラム修正作業以外では絶対に見ない、を徹底すれば命令形式や具体的な命令コードはすぐにわかるようになります。プログラミングをやって見ればわかりますが、実戦で作成するプログラムであっても使用する命令の種類はそう多くないのです。せいぜい数十個です。これはプログラムの規模にあまり影響を受けません。またマシンコードから命令記述をイメージする、ハンド逆アセンブルができるようになるとデバッグ作業の効率は飛躍的に向上します。


レジスターとメモリーアクセスに関する基本的な命令


プログラム割込み

命令の使い方を誤るとCPUは割込みを起こします。これはプログラム割込みと呼ばれます。発生した内容に応じてコードが設定されていて、割込みによってOSに通知します。一般にプログラム割込み=バグと考えられていますが、正確にはそうではありません。
多くの割込みはプログラム・エラーではあるのですが、「仮想アドレスから対応する実記憶を参照しようとしたら、そこにページが無かった」と言うケースもあります。これはページ変換例外と言う割込みで通知されます。MVSはこの割込みを受けると、本当にページが無いのか?実際はページアウトされているだけか?などを調べます。ページアウトされていれば、そのページを読み込めばいいのですからプログラムの実行をエラーにはしません。対応するページが本当に無い場合はアドレスが誤っているのですからMVSによってプログラムはエラーにさせられます。このような時、MVSはCPUからの割込みコードをOSのシステム完了コードに変換してプログラムを異常終了させます。これが S0Cx または S0Dx と言うABENDです。xの部分はCPUの割込みコードに基本的に対応しますが例外もあります。我々は通常のプログラムではCPUからの割込みコードを直接意識しませんので、ここではMVSのABENDコードで解説します。

Filed in S/370アセンブラー講座

アセンブラープログラムの作成(アセンブルJCL)

By kamii - Last updated: 日曜日, 11月 2, 2008

アセンブラーはメインフレーム・コンピューターでは現在でも広く利用されています。業務アプリケーション・プログラムを作成することはなくなってきたものの、OSのEXIT(出口)ルーチンやミドルウェア製品のパラメーター生成など使う機会はまだまだあります。
アセンブルオプションなどについては使用するアセンブラーのマニュアルを参照して下さい。


MVS高水準アセンブラーJCLサンプル

REGIONパラメーターは必要に応じて指定して下さい。アセンブルされたオブジェクトモジュールはバインダーでロードモジュールにするか、ローダーで直接実行します。
アセンブラーは標準のカタログプロシージャーを提供しています(SYS1.PROCLIB)からそちらも参考にしてください。
          ASMAC,ASMACG,ASMACL,ASMACLG


MSPアセンブラーJCLサンプル

リンケージエディターはプログラム名をJQALにすればMVSと同じJCLを使えます。ローダーも同じJCLです。
アセンブラーは標準のカタログプロシージャーを提供しています(SYS1.PROCLIB)からそちらも参考にしてください。
          ASMFC,ASMFCG,ASMFCL,ASMFCLG


VOS3アセンブラーJCLサンプル

リンケージエディターはプログラム名をJSAXLNKにすればMVSと同じJCLを使えます。
アセンブラーは標準のカタログプロシージャーを提供しています(SYS1.PROCLIB)からそちらも参考にしてください。
          ASMC,ASMCG,ASMCL,ASMCLGまたはXASMC,XASMCG,XASMCL,XASMCLG
XASMCが登録されていれば拡張アセンブラー(JOAXASM)が使えます。こちらを使う方がいいでしょう。JLAASSYは24ビット・モードのプログラム用アセンブラーで、31ビット・モード用命令の一部がアセンブルできない、などがあります。

Filed in S/370アセンブラー講座, ありがたいサンプルJCL

COBOLプログラムの作成(COBOLコンパイラー)

By kamii - Last updated: 日曜日, 11月 2, 2008

COBOLはメインフレーム・コンピューターの業務アプリケーション・プログラムでは最も多く使われているプログラミング言語です。バッチ・オンラインを問わず広く利用されています。基本的なコンパイルを行うためのサンプルJCLを示します。コンパイラーも標準のカタログプロシージャーを提供しています(SYS1.PROCLIB等)からそちらも参考にしてください。ユーザーによっては自社のプログラム開発用に標準化されたJCLを作成していたりします。業務用プログラムの場合はそれらの使用が規定されているかも知れません。
コンパイルオプションや追加のDD文などについては使用するCOBOLのマニュアルを参照して下さい。

MVS Enterprise COBOLのコンパイラーJCLサンプル

STEPLIBにコンパイラーが格納されたロードモジュール・ライブラリーを指定します。コンパイルされたオブジェクトモジュールはバインダーでロードモジュールにするか、ローダーで直接実行します。
REGIONパラメーターは必要に応じて指定して下さい。コンパイラーオプションはEXEC文のPARMパラメーターで指定します。長すぎて1行に書ききれない場合は以下のように記述して次の行へ継続できます。


富士通COBOL85のコンパイラーJCLサンプル

リンケージエディターはプログラム名をJQALにすればMVSと同じJCLを使えます。ローダーも同じJCLです。ただしSYSLIB DD文で指定するCOBOLの実行時ライブラリー名はSYS1.COBLIBとなります。


日立COBOL85のコンパイラーJCLサンプル

リンケージエディターはプログラム名をJSAXLNKにすればMVSと同じJCLを使えます。ローダーも同じJCLです。ただしSYSLIB DD文で指定するCOBOLの実行時ライブラリー名はSYS1.COBLIBとなります。

Filed in ありがたいサンプルJCL

03.アセンブラー言語の概説(コーディングの基礎)

By kamii - Last updated: 土曜日, 11月 1, 2008

プログラムの書式

アセンブラー・プログラムは1行が80バイトです。LRECL=80の固定長レコードのデータセットを作成してそこへ書いていきます。区分データセットのメンバーとして登録するのが普通ですが、ちょっとしたプログラムや、命令の動きだけを確認したいような時は、アセンブラーJCL中にSYSINデータとして直接コーディングすることも多いです。

アセンブラーではラベル(名前)は第1桁目、命令はラベルがあればラベルの後ろに1文字以上の空白を置いてから、ラベルがなければ第2桁目以降から書けます。オペランド(命令のパラメーター)は命令の後ろに1文字以上の空白を置いてから書けます。オペランド(オペランドがない命令では命令)の後ろに1文字以上の空白を置いてからコメントが書ける。1行に書ききれないときは72桁目に空白以外の文字を置いて、パラメーターは次の行の16桁目から、コメントは17桁目以降から継続できます。アセンブラーは最低限のルールを守れば基本的に自由コーディングできます。しかし行によって命令の開始桁が違っていたり、人によってスタイルが変わると見にくいので伝統的な決まり事があります。
73桁目以降はSEQ番号ですが使わなくてもかまいません。

1?8桁目はラベル。命令は10桁目からオペランドは16桁目から書きます。OSサービスのマクロなど、命令が6文字以上ある場合は、パラメーター(オペランド)開始位置もそれに合わせてずらします。その場合でも継続行は必ず16桁目からでなければなりません。MVSのアセンブラーではロングネームが使えるので必ずしもこのルールに沿えませんが、伝統的な基本として知っておいてください。
コメントにはいろいろスタイルがありますが、第41桁目、40桁目、36桁目などから書かれることが多いでしょう。行全体をコメントにするなら1桁目に*を置きます。オペランドがない命令の文にコメントを書く場合は命令とコメントの間にカンマ記号を置く癖をつけるといいでしょう。

アセンブラー言語ではコメントは非常に重要です。命令文ごとにコメントを付けるのが良いのですが、単なる命令自体の解説のようなコメントばかり続くと、くどくなるので注意します。何をしてるのか、何のためにやるのか等を残すように心がけるといいでしょう。上のサンプルのように*記号などでコメント欄をカプセルのように囲むこともよく行われます。きちんとしたコメントは十分なドキュメントにもなります。商用プログラムではコメント・カプセルの中にドキュメント自体を書いてしまうことも少なくありません。
形を繕うための外部ドキュメントにさしたる意味はありませんが、プログラム内のきちんとしたコメントはプログラムの保守を行う上でとても役に立ちます。商用プログラムの場合、どんなに素晴らしいものでもコメントがまったく無いようなプログラムは0点と言っても過言ではありません。アセンブラー言語でプログラミングを行う場合は、学習レベルのプログラムを書くときからコメントを付ける癖をつけることを勧めます。


プログラムはCSECTで始まりENDで終わる

プログラムの開始はCSECT命令を使います。一般に最初のセクション開始がSTART、2番目以降のセクション開始がCSECTとされますが、特別な理由がない限りSTARTを使う必要はありません。セクションとはプログラムを構成する要素のことで、実行される命令やデータが展開される制御セクション、外部領域内をフィールドに分割して名前で参照できるようにする見かけセクションなどがあります。CSECTは制御セクションのことで実際に命令やデータが展開されてオブジェクト・モジュールとして出力されます。
プログラムの終了はEND命令を使います。END命令にはプログラムの実行開始位置を指定することもできます。省略すればCSECTの先頭から実行されます。実行開始位置をセクションの途中からにする手法はそれほどむずかしいものではありませんが、慣れるまではわかりにくいので素直にプログラムはセクションの先頭から実行されるものなのだ、と覚えていいでしょう。


ロケーションカウンター

ロケーションカウンターはオブジェクトモジュール内の命令やデータがCSECTの先頭からどれだけ離れているかを示すもので、オフセット、アドレス、番地などとも呼ばれます。あくまでもプログラム(CSECT)の先頭からの相対アドレスです。実際の仮想記憶域にローディングされると、そのローディング・アドレスが加算されて仮想記憶上の主記憶アドレスを形成します。ロケーションカウンターは命令やデータの長さに応じてアセンブラーが適切な番地を計算しますが、必要に応じてプログラマーが変更することもできます。これによってデータ領域の再定義(Redefine)が可能になります。


アセンブラー命令

アセンブラー言語では命令は大きく3種類あります。1つはCPU命令です。マシン命令、機械命令とも言いCPUの1つ1つの動作を指示するものです。次がマクロ命令です。複数の命令をまとめたもので、繰り返し実行する処理などをいちいち書かなくても、マクロ名を書けば対応する命令列に展開してくれるものです。OSのサービス(API)などの多くはマクロ命令を使って呼び出します。メインフレームのマクロは非常に強力な機能を持っていて、活用すれば高級言語並みのコーディングが可能になります。CPU命令とマクロ命令(1部例外を除く)は最終的にオブジェクトモジュールになります。最後が「アセンブラー命令」です。アセンブラー命令は実際にCPUで実行されるものではなく、アセンブラーに対してアセンブル時の動作を指示するものです。いろいろとありますが覚えなければいけないものはそれほど多くありません。



簡単なアセンブラー・プログラムの例

消費税を計算する簡単なプログラムです。どのアセンブラー命令が出てきたか復習してみましょう。計算結果として税込み価格をプログラムの完了コードとして出力します。(OSの仕様で4095円を超えると完了コードでは正しく表示できません)

Filed in S/370アセンブラー講座

MVSのアセンブラーサービス解説書がついに日本語化された

By kamii - Last updated: 金曜日, 10月 31, 2008

アセンブラーでMVSのシステムサービス(GETMAINとかWTOとかいろいろ)を使う際に必要となるのが「Assembler Service Guide」と「Assembler Service Reference」。MVS/ESAまでは日本語版があったのですが、OS/390になってから何故かService ReferenceのVolume2だけが翻訳されていませんでした。最近になって日本語化されたのがわかったので紹介します。(マニュアル一覧ページも修正してあります)

いずれも非APFサービスです。APFサービスのマニュアルは英文を見るしかありません(これもESAまでは翻訳版あったのに)。必要とする人が少ないせいもあるでしょうが、せめて後DFSMS/DFPのマクロサービスとアセンブラーのマニュアルが翻訳されるとアセンブラービギナーには朗報なんですけど…

Filed in つぶやき・雑感