COBOLから呼ばれるアセンブラールーチン
現在ではアセンブラー言語でメインのアプリケーションを作ることはほとんどないものの、COBOLなどで作成されたアプリケーションからサブルーチンとしてのアセンブラープログラムを呼び出すことはよく行われます。COBOLなどの高水準言語プログラムから呼び出されるアセンブラールーチンの作成はさほどむずかしいことではありません。リンケージ規約通りにプログラムを作ればいいのです
しかし逆はかなり面倒です。アセンブラールーチン側で言語処理プログラムの環境を作り上げねばなりません。現実的にアセンブラーでメインのアプリケーションを作り、サブルーチンをCOBOLで作るなどと言うことはまず行われませんからその方法はあえて解説もしません。必要ならコンパイラー(z/OSの場合ならLE)のマニュアルに解説されていますので参照してみてください。
COBOLから呼ばれるサブルーチン例
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- ASMSUB1 CSECT , DEFINE CODE SECTION USING *,RC DEFINE BASE REGISTER STM 14,12,12(13) SAVE CALLER REGISTERS LA 12,0(,15) GR12 -> OUR 1ST BASE ADDRESS LR 15,13 SAVE CALLER SAVEAREA CNOP 0,4 INSURE FULL WORD BOUNDARY BAL 13,*+4+72 AROUND OUR SAVEAREA DC 18F'-1' OUR GPR SAVEAREA ST 15,4(,13) SAVE CALLER SAVEAREA POINTER ST 13,8(,15) SET BACK CHAIN FOR LINK TRACE *---------------------------------------------------------------------* LM R2,R4,0(R1) LOAD CALLING PARMS INTO + GR2 --> POINTER TO PARM1 + GR3 --> POINTER TO PARM2 + GR4 --> POINTER TO PARM3 WTO 'NOW CALLED ASMSUB1' INFORM CALLED MESSAGE MVC 0(8,R4),0(R2) ECHO BACK PARM1 L R0,0(,R3) LOAD PARM2 VALUE CVD R0,DOUBLE CONVERT IT TO PACKED DECIMAL UNPK 8(8,R4),DOUBLE CONVERT IT TO ZONED DECIMAL OI 8+7(R4),C'0' CORRECT SIGN TO READABLE SLR R15,R15 INDICATE RETURN CODE=0 *---------------------------------------------------------------------* L 13,4(,13) LOAD CALLER SAVEAREA L 14,12(,13) RESTORE CALLER GPR14 LM 0,12,20(13) RESTORE CALLER GPR0-12 BR 14 RETURN TO CALLER *---------------------------------------------------------------------* DOUBLE DC D'0' DOUBLE WORD WORKAREA : :
COBOLから渡されるパラメーターはGR1が示すアドレス・パラメーターリストで受け取ることができます。
CALL文のUSINGで指定された順序でパラメーターが格納された領域アドレスが示されます。サンプルでは3つのパラメーターPARM1,PARM2,PARM3を格納した領域アドレスがGR1で示されるアドレス・パラメーターリストで渡されます。PARM3アドレスを示すワードの先頭ビットは最終パラメーターであることを示すため1にセットされます。PARM1からPARM3領域のアドレスをLM命令でGR2からGR4にそれぞれロードします。
PARM1およびPARM2で渡された値をPARM3領域にエコーバックするのがこのサンプルで行っている処理です。PARM1は8バイトの文字、PARM2はフルワードの整数値で、それぞれをPARM3領域の前半8バイトと後半8バイトに格納します。PARM2はバイナリー値を10進文字に変換して設定します。
もちろんどのパラメーターがどのような形式や長さ、意味を持つかはプログラム間のインタフェースとして予め取り決めておきます。
リンケージ規約やアドレス・パラメーターリストについてはリンケージ規約(サブルーチンを作る)も参照して下さい。
- 呼び出すCOBOLは、このサブルーチンを以下のようにして呼び出します。
CALL 'ASMSUB1' USING PARM1 PARM2 PARM3.サブルーチンの処理結果を示す復帰コードはGR15に設定します。呼び出し側のCOBOLプログラムはRETURN-CODE(富士通ではPROGRAM-STATUS)でその値を参照することができます。
呼び出すCOBOL側のサンプル
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- 静的結合されたサブルーチンの呼び出し PROCESS DATA(24) ***************************************************************** * COBOL SAMPLE PROGRAM * ***************************************************************** IDENTIFICATION DIVISION. PROGRAM-ID. COBMAIN1. * ENVIRONMENT DIVISION. CONFIGURATION SECTION. INPUT-OUTPUT SECTION. * DATA DIVISION. WORKING-STORAGE SECTION. 01 PARM1 PIC X(8) VALUE 'ABCDEFGH'. 01 PARM2 PIC S9(008) COMP VALUE 123. 01 PARM3 PIC X(16). * PROCEDURE DIVISION. CALL 'ASMSUB1' USING PARM1 PARM2 PARM3. DISPLAY PARM3 UPON CONSOLE. * STOP RUN. END PROGRAM COBMAIN1. 動的呼び出しによるサブルーチンの呼び出し PROCESS DATA(24) ***************************************************************** * COBOL SAMPLE PROGRAM * ***************************************************************** IDENTIFICATION DIVISION. PROGRAM-ID. COBMAIN1. * ENVIRONMENT DIVISION. CONFIGURATION SECTION. INPUT-OUTPUT SECTION. * DATA DIVISION. WORKING-STORAGE SECTION. 77 PGM-NAME PIC X(8). 01 PARM1 PIC X(8) VALUE 'ABCDEFGH'. 01 PARM2 PIC S9(008) COMP VALUE 123. 01 PARM3 PIC X(16). * PROCEDURE DIVISION. MOVE 'ASMSUB1' TO PGM-NAME. CALL PGM-NAME USING PARM1 PARM2 PARM3. DISPLAY PARM3 UPON CONSOLE. * STOP RUN. END PROGRAM COBMAIN1.
呼び出されるアセンブラー・サブルーチンに対応した呼び出す側のCOBOLのサンプルです。
最初の例はアセンブラールーチンもリンケージエディターで静的に結合されたモジュールの呼び出し例で、2番目はリンケージエディターで結合されていない独立したロードモジュールの呼び出し例です。IBMのEnterprise COBOLによるコーディング例です。細かな構文はメーカーが提供するCOBOLコンパイラーによって多少の違いがあるので利用するコンパイラーのマニュアルも参照して下さい。
パラメーターの値渡し
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- 呼び出すCOBOLルーチン ***************************************************************** * COBOL SAMPLE PROGRAM * ***************************************************************** IDENTIFICATION DIVISION. PROGRAM-ID. COBMAIN2. * ENVIRONMENT DIVISION. CONFIGURATION SECTION. INPUT-OUTPUT SECTION. * DATA DIVISION. WORKING-STORAGE SECTION. 77 PGM-NAME PIC X(8). 01 PARM1 PIC S9(008) COMP VALUE 123. 01 PARM2 PIC S9(008) COMP VALUE 456. 01 PARM3 PIC S9(008) COMP VALUE 789. * PROCEDURE DIVISION. MOVE 'ASMSUB2' TO PGM-NAME. CALL PGM-NAME USING BY VALUE PARM1 PARM2 PARM3. DISPLAY RETURN-CODE UPON CONSOLE. * STOP RUN. END PROGRAM COBMAIN2. 呼ばれるASMルーチン ASMSUB2 CSECT , DEFINE CODE SECTION ASMSUB2 AMODE 31 INDICATE AMODE=31 USING *,RC DEFINE BASE REGISTER STM 14,12,12(13) SAVE CALLER REGISTERS LA 12,0(,15) GR12 -> OUR 1ST BASE ADDRESS LR 15,13 SAVE CALLER SAVEAREA CNOP 0,4 INSURE FULL WORD BOUNDARY BAS 13,*+4+72 AROUND OUR SAVEAREA DC 18F'-1' OUR GPR SAVEAREA ST 15,4(,13) SAVE CALLER SAVEAREA POINTER ST 13,8(,15) SET BACK CHAIN FOR LINK TRACE *---------------------------------------------------------------------* LM R2,R4,0(R1) LOAD CALLING PARMS INTO + GR2 --> PARM1 VALUE + GR3 --> PARM2 VALUE + GR4 --> PARM3 VALUE LR R15,R2 SET RETURN CODE = AR R15,R3 PARM1 + PARM2 + PARM3 AR R15,R4 *---------------------------------------------------------------------* L 13,4(,13) LOAD CALLER SAVEAREA L 14,12(,13) RESTORE CALLER GPR14 LM 0,12,20(13) RESTORE CALLER GPR0-12 BR 14 RETURN TO CALLER
IBMのEnterprise COBOLではパラメーターを値その物で渡すこともできます。CALL文のUSINGパラメーターに「BY VALUE」を指定することでパラメーター領域のアドレスではなく値が渡ります。渡せるパラメーター(値)は2進整数など4バイト以内で渡せるデータに限ります。