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 つぶやき・雑感

02.S/370における数と文字の表現

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

メインフレームに限らずコンピューターのCPUは内部で2進数を使用して演算処理を行っていることはよく知られています。アセンブラー言語のプログラミングではCPUの機械命令を直接使用し、メモリーにも直接アクセスすることになります。COBOLやPL/Iなどのいわゆる高級言語と異なり、数や文字、データがCPUでどのように処理されメモリーにどのように格納されるのかが具体的にわかっている必要があります。そのために数や文字が内部でどのように表現されるかを理解することは大切です。


2進数と16進数

私たちは日常生活では10進数(decimal number)を使います。0から始まって1,2,3と続き7,8,9となったらそれ以上の数字がないので繰り上がって10となります。0?9までの10の数字で表現するため10進数と呼ばれます。ところがコンピューターのCPUは2進数(binary number)を使います。0から始まって1ですが次はそれ以上の数字がないので繰り上がって10となります。0と1の2つの数字で表現するため2進数と呼ばれます。0か1かの2つの状態でしかないので、電気信号のオン/オフに対応させてハードウェアとしての記憶素子に情報を蓄えることができます。この0か1かのいずれの状態によって記憶素子に蓄えられる情報を「ビット(bit)」と呼びます。0の状態がビット・オフ、1の状態がビット・オンとなります。CPUのような機械にとっては0か1かの2進数の方が自然なわけです。なおS/370アーキテクチャでは10進数も扱えますが、基本となる演算処理は内部で2進数に変換されて行われます。

CPUが2進数を使用しメモリーにもビットのON/OFFでデータが蓄えられるならば、例えば100と言う数値は2進数では1100100、379は101111011、1234は10011010010となりますがとても人間が扱える表現方法ではありません。それでもアセンブラー・プログラミングでは数の取り扱いや演算結果、命令動作の確認などでCPUが行うとおりにやってみる必要が生じます。そこでCPUにとっては自然だが人間にとってはやっかいな2進数を扱うために16進数(hexadecimal number)を用います。16進数は0から始まって1,2,3と続き7,8,9となったら次にA,B,C,D,E,Fと続きます。Fの次はそれ以上の数字がないので繰り上がって10となります。0?9、A?Fまでの16の数字で表現するため16進数と呼ばれます。AとかBは数字じゃなくて文字だろうと思うかも知れませんが、それは10進数で考えるからです。16進数ではA,B,C,D,E,Fは数字の1部だと割り切ってください。

16進数は2進数と密接な関係を持ちます。16は2の4乗なので4ビットで表現できます。したがって2進数を4ビットずつ区切れば簡単に16進数に変換できます。先ほど例示した100と言う数値は2進数では1100100なので16進数では64、379は2進数では101111011なので16進数では17B、1234は2進数では10011010010なので16進数では4D2となります。2進数←→10進数変換は計算が必要ですが、2進数←→16進数変換は対応表で簡単に変換できます。実際にプログラミングを始めればいちいち対応表など見なくても直感で変換できるようになります。

ビット操作やマスク値の設定など2進と16進の変換はアセンブラー・プログラミングでは常に必要となります。実際にはさほど長い桁数を変換することはなく、4桁の2進<->1桁の16進に、8桁の2進<->2桁の16進に変換する程度です。なお2進数と10進数の変換計算については、その計算を行うプログラムでも作らない限り必要となることはありません。16進数と10進数も変換には計算が必要でデバッグ作業ではしばしば必要になりますが、n進数計算機能を持つ関数電卓を使えば簡単です。


バイトとワード

メモリーにはデータがビット単位に記憶されます。しかし私たちは1ビット、2ビットと言った長さの数を扱うことはほとんどありません。コンピューターではメモリーを複数の記憶素子をまとめて扱い、CPUがメモリーをアクセスする際の単位とします。S/370アーキテクチャーでは8ビットを1つのグループにしてバイト(byte)を構成します。メモリーはバイト単位にアクセスされるためメモリーアドレスもバイト単位に振られます。本来は1byte=8bitと決まっているわけではありません。初期のコンピューターでは7や9ビットなども使われました。S/360システムが1byte=8bitを採用したことや80年代以降Intel社の8bitや16bitのCPUが普及したので1byte=8bitが定着してしまいました。

S/370アーキテクチャーではバイトは4つにまとめられワード(語)を構成します。演算に使われる汎用レジスターも32bitで構成されています。さらに半分の長さのハーフワード(半語)、倍の長さのダブルワード(倍語)が使われます。そのためCPU命令ではバイト、ハーフワード、ワード(フルワード)、ダブルワードのいずれかの単位でメモリーアクセスすることができます。文字列をまとめて移動できる命令などもありますが、この場合でもバイト単位で合計○○○バイトのデータをメモリーに書き込む、と言った動作になりアクセスはバイト単位に行われます。


数の表現(2進整数)

S/370アーキテクチャーでは整数は2進整数とも呼ばれ、符号を含んで16、32あるいは64ビットで表現されます。メーカーによってはマニュアルに2進固定小数点(Fixed Binary)と載っているものもありますが、実際には整数部のみが使われますので単なる整数と考えてかまいません。呼ばれ方の違いであってIBM、富士通、日立の各社アーキテクチャーに違いはありません。整数は多くのコンパイラー言語ではint型と呼ばれますが、メインフレームのアセンブラーでは integer と言う表現はあまり行われず、そのまま固定小数点とかバイナリーとか言われます。アセンブラー言語が規定した型名で呼ばれる場合もあります。(F型、H型など)

フルワード(4バイト)整数については1部の命令が符号無し32ビット整数として取り扱うこともできる。ダブルワード整数については乗算の積および除算の被除数としてのみ扱うことができる。一般にメインフレームの整数と言えばハーフワードまたはフルワードで考えればよい。C言語で言うshort(16ビット)とlong(32ビット)となる。int型でも32ビットで考えればよい。ちなみにCPUも32ビットCPUである。



符号付き32ビット整数ではマイナス値(負数)は2の補数で表現します。+1はx00000001、0はx00000000ですが、-1はxFFFFFFFFとなります。2の補数は簡単にできます。ビット補数を使えばいいのです。正の数を2進表現します。そしてすべての1を0に、0を1にひっくり返します。それに1を足せばよいのです。他の計算方法もありますがこれがいちばん簡単でしょう。

実際は自分で計算しなくても補数を取るCPU命令が使えます。ただ内部でこう表現されていることを知っているといろいろ便利なこともあります。


文字の表現(キャラクター)

S/370では文字はバイトで表現されます。1文字が1バイト(8bit)です。1バイトの2進数をどの文字に割り当てるかの対応を示すのが文字コードセットです。メインフレームではEBCDIC文字コードセットが使われ、数字文字0?9にはxF0?xF9が割り当てられます。ASCIIと異なり英文字は数字文字より小さなコード値(x81?xE9)が割り当てられます。文字をソートした時の並び順やゾーン10進数のゾーンビットのパターンが異なることは知っておく必要があります。

メモリー上のデータが数値(整数)なのか文字なのかは、そのデータを処理する命令によって決まります。演算命令を使えば整数と見なされますし、文字操作命令を使えば文字または文字列と見なされます。


数の表現(パック10進数)

S/370では2進整数の他に10進数を扱うこともできます。命令で直接数値演算ができる形式がパック10進数、表示や印刷など人間が見てわかる文字形式に変換されたものがゾーン10進数(アンパック10進数)です。

10進数で+1,234を示す例である。数値は8ビットずつに区切られ、先頭4ビットにゾーンビット(xF)、後部4ビットに0?9の値が入る。末尾バイトの先頭4ビットは符号で、+はC、-はDで示す。+はFでもかまわない。パック10進数を演算した結果は命令でゾーン10進数に変換できるが符号はそのままCまたはDで設定される。末尾桁を表示する際にはプログラムで符号ビットを変換するなどして表示可能な文字列に編集する必要がある。

これから新たに事務計算用のプログラムをアセンブラーで作ることはないでしょうが、システム系プログラムでも2進整数の演算結果を人間がわかる形に編集してメッセージなどを組み立てて出力することはよくおこなわれます。このような時はパックやゾーン10進数がデータ変換のために使われます。


数の表現(浮動小数点)

仮数部の長さによって短精度、長精度、拡張精度の3種類があり、16進数でそれぞれ6,14,28桁となる。

S/370での浮動小数点は上図のように表現され、Excess-64方式とも呼ばれる16進浮動小数点です。符号は正負を表し0が+、1が-となります。仮数部は1以下の正の数を表し、小数点が仮数部の直前(ビット8の直前)にあるものとされます。指数部は16の累乗値を表し7ビットの2進数値から64を引いた値がべき数となります。この表現方法がExcess-64です。0?127の指数値は-64?+63のべき数に対応します。浮動小数点値は仮数部に、指数部で示すべき数を使った16のべき乗の値を、掛けたものです。仮数部 * 16^指数部で示すべき数、となります。ESA/390アーキテクチャーではさらに別の方式である2進浮動小数点(インテルCPUなどで使われている)と言うものもサポートされています。
これ以上はややこしいので解説しません。浮動小数点は2^31乗で示される±約21億4700万の整数演算では処理できない大きな数や小数点以下の値の演算が必要な科学技術計算などで使用されます。しかし百分率(%)や平均値などで計算結果を小数点表示(例えば1÷3を0.33と表示)したい場合などは整数演算して表示のしかただけ工夫したり、事務計算で大きな数を扱う場合はパック10進数を使うことも多く、システム系プログラムや事務処理系のアプリケーションで浮動小数点が使われることはほとんどありません。とりあえずは浮動小数点というものがあるんだ、とだけ知っておいて下さい。将来本当に必要になる機会が来たら調べてください。(ちなみに私は1度ぐらいしか使ったことがありません)

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

.このカテゴリーについて

By kamii - Last updated: 水曜日, 10月 29, 2008
このカテゴリーはメインフレーム・コンピューターの代表OSであるIBM社のMVS(z/OS)について、その機能や仕組みに関しての概要を紹介しています。特に断りがない限り富士通のMSP、日立のVOS3にも共通しています。
Filed in .z/OS(MVS),MSP,VOS3のしくみ

GTFトレースの採取とフォーマット

By kamii - Last updated: 火曜日, 10月 28, 2008

MVSにはGTFと呼ばれる汎用トレース機能があります。MVS自身の動作やアプリケーション・プログラムなどの動きをシステムのレベルでトレースする機能です。一般のプログラムのデバッグには向きませんが、アセンブラー言語で作成されたシステム系プログラムなどの動きを追跡したりする目的で利用することもできます。GTFではトレースする項目をイベントと呼び、以下のようなものがあります。

その他ユーザープログラムでデータを書き込むこともできます。

余程のことがない限り一般のユーザーが自ら使うことはありませんが、基盤系ソフトやISV製品などに問題が考えられる時、メーカーやベンダーの依頼でトレースを採ることがありますので、使い方は知っておいた方がいいでしょう。トレースの採取やフォーマットのパラメーターについては依頼する人が必要なものを提示しますから、ユーティリティ名や基本のJCLコーディングなどがわかれば十分です。


GTF起動プロシージャ・サンプル


GTFの起動操作


GTFトレースオプションの例






関連マニュアル

MVS 「zOS MVS:診断のツールと保守援助プログラム」

MVS 「zOS MVS:対話式問題管理システム(IPCS)コマンド」

MSP 「サービスエイド 使用手引書」

VOS3 「システム支援」

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