전체 화면 모드로 어셈블러 프로그램 디버깅

어셈블러에 대한 기본 디버깅 태스크에 대한 설명은 다음 어셈블러 프로그램을 참조하십시오.

예제: 디버깅을 위한 샘플 어셈블러 프로그램

이 절에서 설명하는 자료와 연관된 자세한 정보에 대해서는 다음 주제를 참조하십시오.

예제: 디버깅을 위한 샘플 어셈블러 프로그램

아래 프로그램은 디버깅 태스크를 보여 주기 위해 다양한 주제에서 사용됩니다.

이 샘플 프로그램을 실행하려면 다음 단계를 수행하십시오.

  1. 어셈블러 프로그램을 위한 디버그 파일이 yourid.EQALANGX 데이터셋의 SUBXMPDISPARM 멤버에 있는지 확인하십시오.
  2. Debug Tool을 시작하십시오.
  3. 디버그 파일의 정보를 로드하려면 다음 명령을 입력하십시오.
    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에 대한 디버그 데이터를 로드해야 합니다. 현재 Debug Tool에 디스어셈블리 CU로 알려진 CU에 대해서만 이 작업을 수행할 수 있습니다.

LOADDEBUGDATA 명령(약어로 LDD로 사용됨)을 사용하여 어셈블러 CU로 디스어셈블리 CU를 정의하고 이 CU에 대한 디버그 데이터를 로드하십시오. LDD 명령을 실행할 때 단일 CU 이름을 지정하거나 CU 이름 목록을 괄호로 묶어 지정할 수 있습니다. 지정한 각 이름은 다음 중 하나여야 합니다.

CU 이름이 현재 Debug Tool에 알려진 CU인 경우에는 곧바로 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

앞 섹션에서 설명된 대로 Debug Tool에 CU가 알려지기 전에 LDD 명령을 사용하여 어셈블러 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로 알려졌고 디버그 데이터가 이미 로드되었으므로 이 CU에 대해 다른 LDD를 실행할 필요가 없으며 실행할 수도 없습니다.

단일 어셈블리의 다중 컴파일 단위

Debug Tool은 각 어셈블러 CSECT를 독립 CU(컴파일 단위)로 취급합니다. 어셈블러 소스에 CSECT가 둘 이상 포함된 경우에는 작성하는 EQALANGX 파일에 모든 CSECT에 대한 디버그 정보가 포함됩니다.

대부분의 경우 어셈블리의 모든 CSECT는 로드 모듈 또는 프로그램 오브젝트에 표시됩니다. 그러나 경우에 따라 하나 이상의 어셈블리가 표시되지 않거나 이름이 같은 다른 CSECT로 바뀔 수 있습니다. 따라서 여러 CSECT를 포함하는 어셈블리의 디버그 데이터를 로드하는 방법에는 두 가지가 있습니다.

다음 절에서는 MYPROG와 MYPROGA라는 두 개의 CSECT를 생성하는 예제 어셈블리를 사용합니다. 두 CSECT에 대한 디버그 정보는 yourid.EQALANGX(MYPROG) 데이터셋에 있습니다.

한 LDD 명령을 사용하여 단일 어셈블리의 여러 CSECT에서 디버그 데이터 로드

SET LDD ALL이 적용되는 경우 이 절에 설명된 프로세스를 따르십시오. 모든 CSECT가 로드 모듈 또는 프로그램 오브젝트에 표시되는 경우, 이 프로세스가 여러 CSECT를 포함하는 어셈블리에 대해 디버그 데이터를 로드하는 가장 간단한 방법입니다.

LDD MYPROG 명령을 입력하면 Debug Tool이 MYPROG와 MYPROGA 모두에 대한 디버그 데이터를 찾아서 로드합니다. 디버그 데이터가 로드된 다음 Debug Tool은 이 디버그 데이터를 사용하여 MYPROG와 MYPROGA용으로 CU 두 개를 작성합니다.

독립 LDD 명령을 사용하여 단일 어셈블리의 여러 CSECT에서 디버그 데이터 로드

SET LDD SINGLE이 적용되는 경우 이 절에 설명된 프로세스를 따르십시오.

LDD MYPROG 명령을 입력하면 Debug Tool이 MYPROG와 MYPROGA 모두에 대한 디버그 정보를 찾아서 로드합니다. 그러나 LDD 명령에 MYPROG만 지정했고 SET LDD SINGLE이 적용되므로 Debug Tool은 MYPROG에 대한 디버그 정보만 사용합니다. 그런 다음, LDD MYPROGA 명령을 입력하면 Debug Tool이 다음 단계를 수행합니다.

  1. LDD MYPROG 명령을 입력하기 전에 SET SOURCE 명령을 입력한 경우, Debug Tool은 SET SOURCE 명령을 사용하여 지정한 데이터셋에서 디버그 데이터를 로드합니다.
  2. SET SOURCE 명령을 입력하지 않았거나 Debug Tool이 1단계에서 디버그 정보를 찾지 못한 경우에는 Debug Tool이 이전에 로드한 모든 디버그 정보를 검색합니다. Debug Tool이 MYPROGA의 이름 및 CSECT 길이와 일치하는 이름 및 CSECT 길이를 찾으면 이 디버그 정보를 사용합니다.

디버그 데이터가 로드된 다음 단일 어셈블리에서 여러 CSECT 디버깅

어셈블리의 두 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 명령이 지원되지 않습니다. 어셈블러 루틴이 호출되었을 때는 AT CALL 명령을 사용하여 Debug Tool을 중지하지 마십시오.

어셈블러 프로그램이 중지한 명령문 식별

프로그램에 중단점을 여러 개 설정한 경우 다음 명령을 입력하여 프로그램이 중지된 위치를 Debug Tool이 식별하도록 할 수 있습니다.

QUERY LOCATION

Debug Tool 로그 창에는 다음 예제와 비슷한 메시지가 표시됩니다.

QUERY LOCATION
ENTRY XMPLOAD ::> DISPARM 중단점에서 명령을 실행 중입니다.
프로그램이 현재 블록 XMPLOAD ::> DISPARM를 입력 중입니다.

어셈블러 변수 또는 스토리지 값 표시 및 수정

단일 변수의 컨텐츠를 나열하려면 소스 창에서 변수명이 있는 곳으로 커서를 이동하고 PF4(LIST)를 누르십시오. 로그 창에 값이 표시됩니다. 이는 명령행에 LIST variable을 입력하는 것과 같습니다.

예를 들어, Debug Tool 명령행에 AT 70 ; GO ; 를 입력하여  CALL1  명령문까지 SUBXMP 프로그램을 실행하십시오. 67행이 나타날 때까지 위로 화면이동하십시오. COUNTER 위로 커서를 이동하고 PF4(LIST)를 누르십시오. 로그 창에 다음이 표시됩니다.

LIST ( COUNTER )
COUNTER = 0

COUNTER 값을 1로 수정하려면 COUNTER = 0 행 위에 COUNTER = 1을 입력하고 Enter를 눌러 명령행에 놓은 다음 다시 Enter를 눌러 명령을 실행하십시오.

레지스터 RO에 포함된 주소에서 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'; 명령을 입력하고 Enetr를 눌러 명령을 실행하십시오.

이제 PF2(STEP)를 눌러 DISPARM에 대한 호출로 step into한 다음 CALL2 행에 도달할 때까지 step하십시오. COUNTER 변수의 속성을 보려면 다음 Debug Tool 명령을 실행하십시오.

DESCRIBE ATTRIBUTES COUNTER

로그 창에 다음과 같은 결과가 표시됩니다.

속성: COUNTER
   주소: 1B0E2150, 길이: 4
   DS F

16진 주소를 기호 주소로 변환

어셈블러 또는 디스어셈블리 프로그램을 디버깅하는 중에 16진 주소로 표시되는 기호 주소를 판별할 수 있습니다. LIST 명령을 %WHERE 기본 제공 함수와 함께 사용하면 됩니다. 예를 들어, 다음 명령은 X'1BC5C'의 기호 위치를 나타내는 문자열을 리턴합니다.

LIST %WHERE(X'1BC5C')

명령을 입력하면 Debug Tool이 다음과 같은 결과를 표시합니다.

PROG1+X'12C'

이 결과는 X'1BC5C' 주소가 CSECT PROG1 내의 X'12C' 오프셋에 해당함을 나타냅니다.

조건이 true인 경우에만 어셈블러 행에서 정지

대개 프로그램의 특정 부분이 처음에는 잘 작동하지만 특정 조건에서는 실패하는 경우가 많습니다. 이때 행 중단점을 설정하면 반복해서 GO 명령을 입력해야 하므로 효율적이지 않습니다.

예제: 디버깅을 위한 샘플 어셈블러 프로그램

DISPARM 프로그램에서, COUNTER 변수가 3으로 설정될 때 Debug Tool을 중지하려면 다음 명령을 입력하십시오.

AT 78 DO; IF COUNTER ^= 3 THEN GO; END;

78행은  BUMPCTR  행입니다. 이 명령을 실행하면 Debug Tool이 78행에서 중지됩니다. COUNTER 값이 3이 아니면 프로그램은 계속 실행됩니다. COUNTER 값이 3일 경우, 이 명령을 실행하면 Debug Tool이 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이 중지됩니다.