S/370アーキテクチャーではバイト(8ビット)が情報の基本単位です。EBCDICコードもそうですが、1文字は1バイトで示されます。事務処理や制御系のプログラムでは四則演算よりも文字や文字列の取り扱いの方が多いでしょう。S/370はバイト操作に関する命令も豊富に持っています。
バイト転送命令
1 2 3 4 5 6 7 8 |
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- IC r1,d2(x2,b2) レジスター ← メモリー(バイト) ICM r1,m3,d2(b2) レジスター ← メモリー(バイト) STC r1,d2(x2,b2) レジスター → メモリー(バイト) STCM r1,m3,d2(b2) レジスター → メモリー(バイト) MVI d1(b1),i2 即値 → メモリー(バイト) MVC d1(l,b1),d2(b2) メモリー ← メモリー(バイト) MVCL r1,r2 メモリー ← メモリー(バイト) |
IC、ICM、STC、STCM
IC(Insert Character)命令は、第2オペランドで指定された主記憶の1バイトを第1オペランドで指定されたレジスターの最下位(右端)バイトに格納します。上位3バイトは変更されません。
ICM(Insert Characters under Mask)命令は、第2オペランドで指定された主記憶の連続したnバイトを第1オペランドで指定されたレジスターのm3で示されるマスクビットに対応したバイトに格納します。マスクビットは4ビットで、それぞれのビットはレジスターの各バイトに対応します。例えば、マスクビットが b’1001′ であればレジスターの第1および第4バイト(いちばん左端と右端)に、b’0011′ であればレジスターの第3および第4バイト(下位2バイト)に格納されます。文字が格納されなかった位置のバイト内容は変更されません。
1 2 3 4 5 6 7 8 |
----+----1----+----2----+----3----+----4----+----5----+----6----+ IC R0,=C'A' LOAD C'A' INTO LOW ORDER BYTE ICM R1,B'8000',=X'FF' LOAD X'FF' INTO HIGH ORDER BYTE : SLR R2,R2 CLEAR GR2 ICM R2,B'0011',UHWORD GR2 = 60000 : UHWORD DC AL2(60000) |
ICM命令のマスクビットは 15、X’0F’、B’1111′ のように10進、16進、2進のいずれでの表記も可能です。レジスターのどのバイトに対応させてるかが一目でわかるため、B’0000’の表記がわかりやすいでしょう。符号無しハーフワード2進数をレジスターにロードする場合、値が32768以上になるとLH命令では正しくロードできません。ICM命令をマスクビットB’0011’で使用します。
ICM命令では条件コードがセットされます。
1 … 挿入されたデータの左端ビットは1
2 … 挿入されたデータの左端ビットは0
3 … 使用されない
STC(Store Character)およびSTCM(Store Characters under Mask)命令は、IC、ICMとは逆にレジスターから主記憶へのバイト転送動作です。マスクビットの意味は同じです。
MVI
MVI(Move Immediate)命令は、第2オペランドで指定した1バイトの即値(固定値)を、第1オペランドで指定された主記憶の1バイトに格納します。
1 2 3 4 |
----+----1----+----2----+----3----+----4----+----5----+----6----+ MVI CHAR,C'A' SET C'A' INTO CHAR AREA MVI CHAR,0 SET X'00' INTO CHAR AREA MVI CHAR,X'FF' SET X'FF' INTO CHAR AREA |
MVC
MVC(Move Character)命令は、第2オペランドで指定された主記憶の内容を第1オペランドで指定された主記憶に転送します。転送される長さは最大256バイトで、第1オペランド側で指定します。文字の転送は左から右に1バイトずつ順に行われ、指定した長さ分の転送が終了すると命令は完了します。オペランドが重複する場合を除き、第2オペランド側の主記憶内容は変更されません。
1 2 3 4 5 |
----+----1----+----2----+----3----+----4----+----5----+----6----+ MVI AREA,C' ' SET PADDING CHARACTER MVC AREA+1(L'AREA-1),AREA CLEAR AREA BY BLANK : AREA DC XL256'00' |
上記サンプルは、1バイトずつ転送されることを利用して領域を特定の文字や値で初期化する例です。
MVCL
MVCL(Move Long)命令は、256バイトを超える長さのデータを転送します。第2オペランドで指定された主記憶の内容が、第1オペランドで指定された主記憶に転送されます。転送される長さは受け側、送り側それぞれのオペランドに指定します。受け側<送り側の時は受け側の長さ分だけ転送され、受け側>送り側の時は、送り側の長さ分だけ転送されて受け側の余った領域には指定した充填文字(Padding character)が埋められます。MVCLも文字の転送は左から右に1バイトずつ順に行われます。
オペランドの指定は少々複雑です。送り側と受け側領域それぞれのアドレスおよび長さを、4つのレジスターを使って指定します。第1オペランドは受け側です。r1レジスターにアドレス、r1+1レジスターに長さを格納します。第2オペランドは送り側です。r2レジスターにアドレス、r2+1レジスターに長さを格納します。長さの最大値は16MB-1(2^24)です。第2オペランド側r2+1レジスターの先頭バイトには充填文字を格納します。レジスターは乗除算同様に偶数番号レジスターと奇数番号レジスターをペアにして使い、必ず偶数側のレジスター番号を指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
----+----1----+----2----+----3----+----4----+----5----+----6----+ LA R0,AREA1 MOVE AREA2 TO ARE1 AND LA R1,480 FILL X'FF' INTO UNMOVED LA R14,AREA2 SPACE. LA R15,320 ICM R15,B'1000',=X'FF' LOAD PAD CHARACTER MVCL R0,R14 MOVE LONG DATA LA 0,BUFFER LOAD BUFFER ADDRESS LA 1,512 LOAD BUFFER LENGTH SLR 15,15 INDICATE NULL CLEAR MVCL 0,14 CLEAR BUFFER AREA : AREA1 DC 480C' ' AREA2 DC 320C' ' BUFFER DC 512X'00' |
256バイト以上の領域間のデータ転送と領域クリアーの例です。領域をクリアーするには送り側の長さを0にすればいいです。この場合、対になっている偶数レジスターにはどんな値が入っていてもかまいません。長さが0の場合は、送り側記憶域アドレスとして参照されません。
MVCL命令は複雑なので簡単な使い方だけ紹介しました。MVC命令と異なり、命令実行中や実行後にレジスター内容が変更される、条件コードが設定される、誤ったオペランド重複はリジェクトされる(*1)等の特性があります。詳細は命令のリファレンス・マニュアルを読んで下さい。
*1 前述のMVCのサンプルでは256バイトの領域を空白埋めする例を示したが、同様のことをMVCLでやろうとしてもオペランド重複として拒否されてしまう。
変換・探索・編集命令
以降の命令は、アセンブラー・ビギナーには扱いが面倒なものです。こんなものもあるのかという程度で名前だけ覚えるぐらいでもいいです。必要に迫られたら、リファレンス・マニュアルなどを参考にしてトライして見て下さい。
1 2 3 4 5 |
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- TR d1(l,b1),d2(b2) メモリー(変換)← テーブル TRT d1(l,b1),d2(b2) メモリー(探索)← テーブル ED d1(l,b1),d2(b2) メモリー(編集)← パック10進数 EDMK d1(l,b1),d2(b2) メモリー(編集)← パック10進数 |
TR、TRT
TR(Translate)命令は、その名の通り主記憶上のデータを変換する命令です。第1オペランドで指定された主記憶の内容が、第2オペランドで指定されたテーブル(変換表)に従って変換されます。変換される長さは最大256バイトで、第1オペランド側で指定します。第2オペランド側のテーブル内容は変更されません。
第2オペランドにTABLEと言う名前のテーブル領域を指定したとします。第1オペランドの主記憶のデータがx00の時、そのx00はTABLEの先頭からx00バイト離れた位置(TABLE+x00)のバイト内容に置き換わります。第1オペランドの主記憶のデータがx28の時、そのx28はTABLEの先頭からx28バイト離れた位置(TABLE+x28)のバイト内容に置き換わります。TR命令は文字コードの変換(例えばEBCDICからASCII)、2進→16進変換、非表示文字の変換(*2)などに使われます。
1 2 3 4 5 6 7 8 |
----+----1----+----2----+----3----+----4----+----5----+----6----+ TR WORKAREA,TABLE TRANSLATE EBCDIC A-H TO ASCII : WORKAREA DC CL8'ABCDEFGH' STRING TO BE TRANSLATED TABLE DC XL256'00' TRANSLATE TABLE AREA ORG TABLE+C'A' LOCATE TO TABLE+X'C1' DC AL1(X'41',X'42',X'43',X'44',X'45',X'46',X'47',X'48') ORG , CORRECT LOCATION COUNTER |
かなり手を抜いたテーブルですが、EBCDICのAからHまでの文字をASCIIコードに変換する例です。限られた範囲の文字を変換するだけなら256バイトを真面目に用意する必要はありません。OS/390アセンブラーハンドブックにも載ってます。
*2 例えば、メモリーダンプなどで文字ではないバイナリー値などを画面にそのまま表示すると意味不明の文字になったりするので、それを防ぐ為に空白やピリオドに置換えたりする。
TRT(Translate and Test)命令は、TRと似ていますが記憶域データの変換はされません。主に、文字列内の特定文字を探索するために使われます。第1オペランドで指定された主記憶の内容が、第2オペランドで指定されたテーブル(変換表)に従って探索されます。探索される長さは最大256バイトで、第1オペランド側で指定します。第1オペランド側の主記憶内容は、アーギュメントとも呼ばれます。第1および第2オペランド側のテーブル内容は変更されません。
第2オペランドにTABLEと言う名前のテーブル領域を指定したとします。テーブルはx00(NULL値)でクリアーします。空白文字を探したければTABLE+x40の位置に、文字Aを探したければTABLE+xC1の位置にそれぞれ0以外の値を設定します。これはファンクション・バイトと呼ばれます。複数の文字を探す場合は文字毎に値を変えればどの文字が見つかったかが簡単にわかります。TRT命令は読み込んだデータ内の区切り文字やコマンド・バイトなどを探す際などに使われます。
TRT命令は条件コードがセットされます。
1 … アーギュメントの途中で0でないファンクションバイトが検出された(文字がデータの途中に見つかった)
2 … アーギュメントの最後で0でないファンクションバイトが検出された(文字がデータの最後に見つかった)
3 … 使用されない
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
----+----1----+----2----+----3----+----4----+----5----+----6----+ SLR R2,R2 CLEAR FUNCTION REGISTER TRT DOCS,SCANTAB FIND C' ' AND C'.' IN DOCUMENTS BC B'1000',NOTFOUND IF NOT FOUND B *+4(R2) BRANCH BY FUNCTION CHARACTER + GR1 -> FOUND ADDRESS + GR2 -> FUNCTION(WHICH CHARACTER EX 0,* 00 ABTER(S0C3)(ITS IMPOSSIBLE) B DOBLANK 04 FUNCTION C' ' BLANK B DOPERIOD 08 FUNCTION C'.' PERIOD : DOCS DC C'HELLO! TODAY IS VERY FINE.' SCANTAB DC XL256'00' TRANSLATE TABLE AREA ORG SCANTAB+C' ' LOCATE TO TABLE+X'40' DC AL1(04) ORG SCANTAB+C'.' LOCATE TO TABLE+X'C1' DC AL1(08) ORG , CORRECT LOCATION COUNTER |
DOCSと言う名前の領域データを探索して、空白またはピリオドを探します。空白が見つかったら4、ピリオドなら8をファンクション・バイトとして設定しています。文字が見つかった場合(CC=1または2)、GR1には見つかったアドレスが、GR2の最下位バイトには対応するファンクション・バイト値が設定されます。GR2の上位3バイトは変更されません。文字が見つからなければ(CC=0)GR1とGR2は変更されません。
ED、EDMK
パック10進数を人間が見てわかるようにするために、UNPK命令によってゾーン10進数に変換する方法がありました。ここでは編集しながらゾーン10進数に変換してくれるED(Edit)およびEDMK(Edit Mark)命令を紹介します。
第2オペランドで指定された主記憶のパック10進数が、第2オペランドで指定された主記憶上の編集パターンに従って変換されます。変換される長さは、第1オペランド側である編集パターンのバイト数で指定します。変換元のパック10進数の内容は変更されません。
種類 | 値 | 備考 | 埋め文字 | 任意の文字 | (一般的には空白) | 数字選択文字 | x20 | ここに数字桁がゾーン変換されて入る。 | 有意開始文字 | x21 | この次のx20パターンから先行ゼロを出す。 通常は10の位をx21にすればよい。 |
その他 | 任意の文字 | そのまま出力される。3桁ごとにカンマで区切ったり、小数点記号を置いたりする。 最終桁よりも右側に置かれた場合、元のパック10進数が正の場合、埋め文字に置き換わってしまう。それを防ぐには元の数値を一旦マイナス値に変えるか、第1オペランドの長さを短くしてED命令を実行するなどの工夫をする。 |
---|
ED命令は慣れるまでは期待した結果に編集されず、何度もトライ&エラーを繰り返す命令でもあります。命令リファレンスを見ても最初はよくわからないかも知れません。地道に試して慣れていって下さい。面倒な命令ですが、理解できるとアウトプットの編集が楽になります。
「000012345」と言う表示は間違いではありませんが、テストや自分だけで使うツールならともかく、正式品のプログラムなら「 12,345」と言う編集を面倒がらずに「やろうと思えばいつでもできる」ぐらいでいられた方がいいでしょう。暗記する必要などありません、リファレンス見ながらで十分です。
EDMK命令はED命令と同じですが、命令実行後にGR1に先頭の有効数字桁のアドレスが格納されます。(ただし格納されない例外条件もあるのでリファレンスマニュアルを参照)この機能によって先頭桁の前にマイナス記号や通貨記号などを付けることが容易になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
----+----1----+----2----+----3----+----4----+----5----+----6----+ ① 3桁毎のカンマ編集 L 0,=F'2147483647' LOAD INTEGER CVD 0,DECIMAL CONVERT TO DECIMAL MVC FORMAT1,EDITMASK SET EDIT PATTERN MASK ED FORMAT1,DECIMAL+2 EDIT Z,ZZZ,ZZZ,ZZ9 : DECIMAL DC D'0' FORMAT1 DC CL15' ' EDITMASK DC XL15'4020206B2020206B2020206B202120' ② 3桁毎のカンマ編集(負数の時有効桁の先頭に-記号を付ける) L 0,=F'-123456789' LOAD INTEGER CVD 0,DECIMAL CONVERT TO DECIMAL MVC FORMAT2,EDITMASK SET EDIT PATTERN MASK LA 1,FORMAT2+L'FORMAT2-1 PRESET SIGNIFICANT DIGIT EDMK FORMAT2,DECIMAL+2 EDIT Z,ZZZ,ZZZ,ZZ9 BNM *+4+2+4 IF NOT MINUS, BCTR 1,0 LOCATE TO SIGN MARK FIELD MVI 0(1),C'-' SET MINUS SIGN MARK : DECIMAL DC D'0' FORMAT2 DC CL15' ' EDITMASK DC XL15'4020206B2020206B2020206B202120' ③ 百分率編集(ZZ9.9%) L 0,=F'324' LOAD INTEGER 32.4% CVD 0,DECIMAL CONVERT TO DECIMAL MVC FORMAT3,EDITMASK SET EDIT PATTERN MASK ED FORMAT3(7),DECIMAL+5 EDIT ZZ9.9% : FORMAT3 DC CL8' ' EDITMASK DC XL8'40202021204B206C' |