アセンブラーに関する基本的なデバッグ・タスクの説明では、下記 のアセンブラー・プログラムを参照します。
ここで述べた内容に関して詳しくは、以下のトピックを参照してください。
下記のプログラムは、デバッグ・タスクを示すために各種のトピックで取り上げられます。
このサンプル・プログラムを実行するには、以下のステップを行います。
LDD (SUBXMP,DISPARM)
このプログラムは、アセンブラー・サブルーチン (DISPARM) を呼び出す アセンブラー・メインルーチン (SUBXMP) の簡単な例です。
ロード・モジュール: XMPLOAD
SUBXMP.ASM
**************************************************************
* *
* NAME: SUBXMP *
* *
* A simple main assembler routine that brings up *
* Language Environment, calls a subroutine, and *
* returns with a return code of 0. *
* *
**************************************************************
SUBXMP CEEENTRY PPA=XMPPPA,AUTO=WORKSIZE
USING WORKAREA,R13
* Invoke CEEMOUT to issue the greeting message
CALL CEEMOUT,(HELLOMSG,DEST,FBCODE),VL,MF=(E,CALLMOUT)
* No plist to DISPARM, so zero R1. Then call it.
SLR R0,R0
ST R0,COUNTER
LA R0,HELLOMSG
SR R01,R01 ssue a message
CALL DISPARM CALL1
* Invoke CEEMOUT to issue the farewell message
CALL CEEMOUT,(BYEMSG,DEST,FBCODE),VL,MF=(E,CALLMOUT)
* Terminate Language Environment and return to the caller
CEETERM RC=0
* CONSTANTS
HELLOMSG DC Y(HELLOEND-HELLOSTR)
HELLOSTR DC C'Hello from the sub example.'
HELLOEND EQU *
BYEMSG DC Y(BYEEND-BYESTART)
BYESTART DC C'Terminating the sub example.'
BYEEND EQU *
DEST DC F'2' Destination is the LE message file
COUNTER DC F'-1'
XMPPPA CEEPPA , Constants describing the code block
* The Workarea and DSA
WORKAREA DSECT
ORG *+CEEDSASZ Leave space for the DSA fixed part
CALLMOUT CALL ,(,,),VL,MF=L 3-argument parameter list
FBCODE DS 3F Space for a 12-byte feedback code
DS 0D
WORKSIZE EQU *-WORKAREA
PRINT NOGEN
CEEDSA , Mapping of the dynamic save area
CEECAA , Mapping of the common anchor area
R0 EQU 0
R01 EQU 1
R13 EQU 13
END SUBXMP Nominate SUBXMP as the entry point
DISPARM.ASM
**************************************************************
* *
* NAME: DISPARM *
* *
* Shows an assembler subroutine that displays inbound *
* parameters and returns. *
* *
**************************************************************
DISPARM CEEENTRY PPA=PARMPPA,AUTO=WORKSIZE,MAIN=NO
USING WORKAREA,R13
* Invoke CEE3PRM to retrieve the command parameters for us
SLR R0,R0
ST R0,COUNTER
CALL CEE3PRM,(CHARPARM,FBCODE),VL,MF=(E,CALL3PRM) CALL2
* Check the feedback code from CEE3PRM to see if everything worked.
CLC FBCODE(8),CEE000
BE GOT_PARM
* Invoke CEEMOUT to issue the error message for us
CALL CEEMOUT,(BADFBC,DEST,FBCODE),VL,MF=(E,CALLMOUT)
B GO_HOME Time to go....
GOT_PARM DS 0H
* See if the parm string is blank.
LA R1,1
SAVECTR ST R1,COUNTER
CL R1,=F'5' BUMPCTR
BH LOOPEND
LA R1,1(,R1)
B SAVECTR
LOOPEND DS 0H
CLC CHARPARM(80),=CL80' ' Is the parm empty?
BNE DISPLAY_PARM No. Print it out.
* Invoke CEEMOUT to issue the error message for us
CALL CEEMOUT,(NOPARM,DEST,FBCODE),VL,MF=(E,CALLMOUT)
B GO_TEST Time to go....
DISPLAY_PARM DS 0H
* Set up the plist to CEEMOUT to display the parm.
LA R0,2
ST R0,COUNTER
LA R02,80 Get the size of the string
STH R02,BUFFSIZE Save it for the len-prefixed string
* Invoke CEEMOUT to display the parm string for us
CALL CEEMOUT,(BUFFSIZE,DEST,FBCODE),VL,MF=(E,CALLMOUT)
* AMODE Testing
GO_TEST DS 0H
L R15,INAMODE24@
BSM R14,R15
InAMode24 Equ *
LA R1,DEST
O R1,=X'FF000000'
L R15,0(,R1)
LA R15,2(,R15)
ST R15,0(,R1)
L R15,INAMODE31@
BSM R14,R15
InAMode31 Equ *
* Return to the caller
GO_HOME DS 0H
LA R0,3
ST R0,COUNTER
CEETERM RC=0
* CONSTANTS
DEST DC F'2' Destination is the LE message file
CEE000 DS 3F'0' Success feedback code
InAMode24@ DC A(InAMode24)
InAMode31@ DC A(InAMode31+X'80000000')
BADFBC DC Y(BADFBEND-BADFBSTR)
BADFBSTR DC C'Feedback code from CEE3PRM was nonzero.'
BADFBEND EQU *
NOPARM DC Y(NOPRMEND-NOPRMSTR)
NOPRMSTR DC C'No user parm was passed to the application.'
NOPRMEND EQU *
PARMPPA CEEPPA , Constants describing the code block
* ===================================================================
WORKAREA DSECT
ORG *+CEEDSASZ Leave space for the DSA fixed part
CALL3PRM CALL ,(,),VL,MF=L 2-argument parameter list
CALLMOUT CALL ,(,,),VL,MF=L 3-argument parameter list
FBCODE DS 3F Space for a 12-byte feedback code
COUNTER DS F
BUFFSIZE DS H Halfword prefix for following string
CHARPARM DS CL255 80-byte buffer
DS 0D
WORKSIZE EQU *-WORKAREA
PRINT NOGEN
CEEDSA , Mapping of the dynamic save area
CEECAA , Mapping of the common anchor area
MYDATA DSECT ,
MYF DS F
R0 EQU 0
R1 EQU 1
R2 EQU 2
R3 EQU 3
R4 EQU 4
R5 EQU 5
R6 EQU 6
R7 EQU 7
R8 EQU 8
R9 EQU 9
R10 EQU 10
R11 EQU 11
R12 EQU 12
R13 EQU 13
R14 EQU 14
R15 EQU 15
R02 EQU 2
END
アセンブラー・プログラムをデバッグするにはその前に、コンパイル単位 (CU) をアセンブラー CU として定義し、CU のデバッグ・データをロードする必要があります。これは、逆アセンブリー CU として現在 Debug Tool に認識されている CU に対してのみ行うことができます。
LOADDEBUGDATA コマンド (LDD と短縮される) を使用して、逆アセンブリー CU をアセンブラー CU として定義し、この CU のデバッグ・データをロードさせます。 LDD コマンドを実行する場合、単一の CU 名を指定するか、 または括弧で囲んだ CU 名のリストを指定することができます。 指定されるそれぞれの名前は、以下のいずれかでなければなりません。
CU 名が現在 Debug Tool に認識されている場合、その CU は即時にアセンブラー CU としてマークされ、以下のようにして、そのデバッグ・データのロードが試みられます。
LDD コマンドに指定した CU 名が現在 Debug Tool に認識されていない場合、 メッセージが出され、その名前の CU が認識される (現れる) まで、LDD コマンドは据え置かれます。 その時点で CU が自動的にアセンブラー CU として作成され、デフォルト・データ・セット名または現行の SET DEFAULT LISTINGS 指定を使用してデバッグ・データのロードが試みられます。
CU に対して LDD コマンドを入力した後は、CU を逆アセンブリー CU として表示できません。
LDD コマンドを入力した後 Debug Tool が関連のアセンブラー・デバッグ・データを見つけられない場合、 その CU は逆アセンブリー CU ではなくアセンブラー CU です。 この CU に対してもう一度 LDD コマンドを入力することはできません。 ただし、SET DEFAULT LISTING コマンドまたは SET SOURCE コマンドを入力して、 関連のデバッグ・データを別のデータ・セットからロードすることができます。
前の節で説明したように、LDD コマンドを使用して、CU が Debug Tool に認識される前に、その CU をアセンブラー CU として識別することができます。 これを据え置き LDD と呼びます。 この場合、CU が現れると、即時にアセンブラー CU としてマークされ、 デフォルト・データ・セット名または現在 SET DEFAULT LISTINGS で指定されているデータ・セットから、デバッグ・データのロードが試みられます。
この方法でデバッグ・データを見つけられない場合は、CU が現れた後で SET SOURCE または SET DEFAULT LISTINGS コマンドを使用して、正しいデータ・セットからデバッグ・データ がロードされるようにしなければなりません。 これは、以下のようなコマンドを使用して行うことができます。
AT APPEARANCE mycu SET SOURCE (mycu) hlq.qual1.dsn
あるいは、"mycu" が現れた後、その他の理由で停止するまで待機してから、SET SOURCE または SET DEFAULT LISTING コマンドを使用して、Debug Tool に正しいデータ・セット を指示します。
有効なアセンブラー・デバッグ・データがロードされた CU が無くなった後、 再表示する場合 (例えば、ロード・モジュールが削除された後で、再ロードされた場合)、 その CU は即時にアセンブラー CU としてマークされ、デバッグ・データは、 前に正常にロードされていたデータ・セットから再ロードされます。
その CU がアセンブラー CU として既に認識されており、 デバッグ・データが既にロードされているので、その CU に対する別の LDD は、 実行する必要がありません (実行できません)。
Debug Tool は、各アセンブラー CSECT を別々のコンパイル単位 (CU) として扱います。 アセンブラー・ソースが複数の CSECT を含む場合、作成する EQALANGX ファイルには すべての CSECT についてのデバッグ情報が含まれます。
ほとんどの場合、アセンブリー内のすべての CSECT はロード・モジュールまたは プログラム・オブジェクトに存在します。ただし 1 つ以上のアセンブリーが 存在しない場合や、同じ名前のほかの CSECT に置換される場合もあります。 そのため、複数の CSECT を含むアセンブリーのデバッグ・データをロードする 方法は 2 つあります。
次のセクションでは、MYPROG と MYPROGA という 2 つの CSECT を生成する アセンブリーの例を使用します。 これら両方の CSECT のデバッグ情報は、データ・セット yourid.EQALANGX(MYPROG) にあります。
SET LDD ALL が有効である場合、このセクションに記述されているプロセスを実行してください。 すべての CSECT がロード・モジュールやプログラム・オブジェクトに存在する場合、 このプロセスが複数の CSECT を含むアセンブリーのデバッグ・データをロードする 最も簡単な方法です。
コマンド LDD MYPROG を入力すると、Debug Tool は MYPROG と MYPROGA の 両方のデバッグ・データを検索してロードします。 デバッグ・データがロードされると、Debug Tool はデバッグ・データを使用して、 MYPROG と MYPROGA を対象とする 2 つの CU を作成します。
SET LDD SINGLE が有効である場合、このセクションに記述されているプロセスを実行してください。
コマンド LDD MYPROG を入力すると、Debug Tool は MYPROG と MYPROGA の両方のデバッグ情報を検索してロードします。 ただし、LDD コマンドに MYPROG のみを指定し、SET LDD SINGLE が 有効であるため、Debug Tool は MYPROG のデバッグ情報のみを使用します。 その後、 コマンド LDD MYPROGA を入力すると、Debug Tool は以下のステップを実行します。
アセンブリー内の両方の CSECT のデバッグ・データをロードすると、 いずれかのコンパイル単位のデバッグを開始することができます。 両方の CSECT の内容がソース・リストに表示されていても、現在限定対象となっている コンパイル単位内にしかブレークポイントを設定できません。
ソース・リストを見る場合、ある CSECT 内の現在限定対象外の全行にはそのオフセット・フィールドの直前とステートメント番号の直後にアスタリスクが入ります。このアスタリスクの付いたステートメント上に行ブレークポイントまたはステートメント・ブレークポイントを設定したい場合、含んでいるコンパイル単位に対して最初に限定する必要があります。そのためには以下のコマンドを使用します。
SET QUALIFY CU compile_unit_name;
このコマンドの入力後に、これらのアスタリスクはブレークポイント設定対象の行から除去されます。アスタリスクがないことの意味は、その行上に行ブレークポイントまたはステートメント・ブレークポイントを設定可能であることを示します。
コンパイル単位のデバッグ・データをロードするまでは、 SET QUALIFY コマンドを使用してアセンブラー・コンパイル単位に 限定することはできません。
このトピックでは、AT ENTRY コマンドを使用して、ルーチンが呼び出された直後に停止する方法を説明します。これらのコマンドの説明には、例: デバッグを行うためのアセンブラー・プログラムの例 が使用されます。
DISPARM ルーチンが呼び出された後で停止するには、次のコマンドを入力します。
AT ENTRY DISPARM
DISPARM ルーチンが呼び出された後に、R1 が 0 である場合にのみ停止するには、以下のコマンドを入力します。
AT ENTRY DISPARM WHEN R1=0;
AT CALL コマンドは、アセンブラー・ルーチンでサポートされません。 アセンブラー・ルーチンが呼び出されたときに Debug Tool を停止するのに AT CALL コマンド を使用しないでください。
プログラム内に多くのブレークポイントを設定している場合、以下のコマンドを入力して、プログラムが停止した場所を Debug Tool によって特定することができます。
QUERY LOCATION
Debug Tool ログ・ウィンドウには、次の例と同様なものが表示されます。
QUERY LOCATION You are executing commands in the ENTRY XMPLOAD ::> DISPARM breakpoint. The program is currently entering block XMPLOAD ::> DISPARM.
単一の変数の内容をリストするには、ソース・ウィンドウ内の変数名の出現箇所にカーソルを移動し、PF4 (LIST) を押します。値はログ・ウィンドウに表示されます。これは、コマンド行に LIST variable を入力するのと同等です。
例えば、SUBXMP プログラムを CALL1 というラベルの付いたステートメントまで 実行するには、Debug Tool コマンド行に AT 70 ; GO ; と入力します。行 67 が表示されるまでスクロールします。 カーソルを COUNTER の上に移動し、PF4 (LIST) を押します。 これにより、ログ・ウィンドウに次のように表示されます。
LIST ( COUNTER ) COUNTER = 0
COUNTER の値を 1 に変更するには、COUNTER = 0 の行に COUNTER = 1 と 上書きし、Enter を押してこれをコマンド行に置き、Enter を再度押してこのコマンドを出します。
レジスター R0 に入ったアドレスの、2 バイト先のストレージ 16 バイトの内容をリストするには、 コマンド行でコマンド LIST STORAGE(R0->+2,16) を入力し、Enter を押します。 指定されたストレージの内容がログ・ウィンドウに表示されます。
LIST STORAGE( R0 -> + 2 , 16 ) 000C321E C8859393 96408699 969440A3 888540A2 *Hello from the s*
このストレージの最初の 2 バイトを X'C182' に変更するには、コマンド行で コマンド R0->+2 <2> = X'C182'; を入力し、Enter を押してコマンドを出します。
次に、PF2 (STEP) を押して DISPARM の呼び出しにステップイントゥし、CALL2 という ラベルの付いたステートメントまで進みます。変数 COUNTER の属性を表示するには、次の Debug Tool コマンドを出します。
DESCRIBE ATTRIBUTES COUNTER
結果はログ・ウィンドウに次のように表示されます。
ATTRIBUTES for COUNTER Its address is 1B0E2150 and its length is 4 DS F
アセンブラー・プログラムまたは逆アセンブリー・プログラムをデバッグする 場合、16 進アドレスで表されたシンボリック・アドレスを判別したい場合があります。 これは、%WHERE 組み込み関数を指定した LIST コマンドを使用することによって行うことができます。 例えば、以下のコマンドは、X'1BC5C' のシンボリック・ロケーション を示すストリングを戻します。
LIST %WHERE(X'1BC5C')
このコマンドを入力した後、Debug Tool は以下の結果を表示します。
PROG1+X'12C'
この結果は、アドレス X'1BC5C' が、CSECT PROG1 内のオフセット X'12C' に対応していることを示します。
ユーザー・プログラムの特定の部分が、最初の数千回は 正常に機能しますが、ある条件のもとでは失敗するということが よくあります。行のブレークポイントの設定では、GO コマンドを繰り返し入力する必要があるため非効率的です。
DISPARM プログラムで COUNTER 変数が 3 に設定されている場合に Debug Tool を停止するには、 次のコマンドを入力します。
AT 78 DO; IF COUNTER ^= 3 THEN GO; END;
行 78 は、 BUMPCTR というラベルが付いた行です。 このコマンドにより、Debug Tool は行 78 で停止します。COUNTER の値が 3 でない場合、プログラムは続行します。 このコマンドにより、Debug Tool は COUNTER の値が 3 の場合にのみ、行 78 で停止するようになります。
プログラミング・エラーの検討中に、どのような順序の呼び出しがそのプログラミング・エラーを もたらしたのかを把握したいことがよくあります。この順序は、トレースバック、 または呼び出し元のトレースバックと呼ばれます。 トレースバック情報を取得するには、次のコマンドを入力します。
LIST CALLS
例えば、次のコマンドで SUBXMP の例を実行すると、 ログ・ウィンドウに呼び出し元のトレースバックが表示されます。
AT ENTRY DISPARM GO LIST CALLS
ログ・ウィンドウには、次のような情報が表示されます。
At ENTRY IN Assembler routine XMPLOAD ::> DISPARM. From LINE 76.1 IN Assembler routine XMPLOAD ::> SUBXMP.
プログラムの実行中に、あるストレージが予期せずにその値を変更し、いつ、どこでこのようなことが生じたかを調べたい場合があります。 以下では、値が予期せず変更されたことをプログラムが検出する例を考えます。
L R0,X'24'(R3)
ロード中のオペランドのアドレスを調べるには、次のコマンドを入力します。
LIST R3->+X'24'
その結果が X'00521D42' であったとします。このアドレスから始まる次の 4 バイトのストレージの値の変更を監視する ブレークポイントを設定するには、次のコマンドを出します。
AT CHANGE %STORAGE(X'00521D42',4)
プログラムの実行中にこのストレージの値が変わると、Debug Tool は停止します。