Docstoc

Convert ASM2COBOL

Document Sample
Convert ASM2COBOL Powered By Docstoc
					Converting z/OS assembler code
to COBOL
Level: Advanced

Sandhya Prabhakaran (mailto:saprabha@in.ibm.com?subject=Converting z/OS assembler code to
COBOL), Systems Software Engineer, IBM

17 Nov 2006
Updated 12 Jan 2007

        Learn the advantages of converting your low-level z/OS® assembler code to the
        more flexible, user-friendly COBOL language. Understand some of the differences
        between the languages and some basics about converting your programs. Code
        samples in each language illustrate the differences. [In the article update, a
        space was removed between R1 and R2 in the section "Understanding the basics
        of an assembler instruction," and Listing 3 was divided into two code samples. -
        Ed.]

Introduction: Why convert to COBOL?
In today's programming, with programs written in high-level and scripting languages, it is easy to
forget that a significant portion of enterprise IT function lives on big iron mainframes in the form
of z/OS assembler code. You may find that your own investment in assembler applications is
reaching its end and that you need to move to a higher level language, but you are not ready to
jump all the way to Java™ and other newer languages. Remember that COBOL language, though
not today's hottest technology under the sun (by a long shot), still offers dramatically greater
flexibility and ease-of-coding than assembler language. Though there seems to be a rush to Java
and other Web-enabled languages, COBOL remains the only proven 4GL language that handles
large volumes of data to be processed on the mainframe.
Coding in assembler language is not like coding in any other language, because assembler lacks
the flexibility and user-friendliness of a high-level language. A low-level language directly
addresses memory-resident areas called registers; in any high-level language, the variables
handle this function.
There are several reasons to convert a low-level assembler program to the higher level COBOL
language. The main reasons are:


       There might be licensing issues with assembler code, and the code might expire.
        Licensing is often expensive, and you risk losing rights to use the code.
       Assembler code can be difficult to maintain because of a shortage of experienced
        professionals.
       Programming in assembler language is not as flexible or user-friendly as COBOL
        language.

This article introduces you to some of the intricacies of the assembler language and provides
general guidance for how to convert assembler code to COBOL. Code samples show the same
program in assembler and COBOL to illustrate the differences.




Understanding the basics of an assembler instruction
An assembler instruction is generally divided into the following four parts:


       Label
       Mnemonic (the operation to be performed)
       Operands and parameters
         Comment

The label and comment are not required.
For example, consider the following instruction:
ADD-ROUTINE AR R1,R2
This means that the contents in R1 and R2 are added, and the result is stored in R1. The various
parts are as follows:


         ADD-ROUTINE is the label.
         AR is the mnemonic for ADD REGISTERS.
         R1 and R2 are the operands. The contents of these registers are added, and the sum is
          placed in R1).


In assembler, registers are memory locations.




Exploring the framework of an assembler program
Assembler programs generally follow a framework that consists of the following parts:
SAVEAREA HANDLING
          This is an initial housekeeping routine that saves the current register contents so that the
          registers can be used for programming purposes in the assembler routine and restored to
          their original contents after the routine is completed.


CSECT (code section)
          In this part of the program, the variables used in the assembler routine are defined as
          DC, DS, and EQU, and the logic is coded.

USING statement
          The assembler language uses this statement to set the location of the current base
          register.


DSECT (dummy section) declarations
         When other programs call the assembler routines, these declaractions within the
         assembler program receive the parameters of the calling programs.
Listing 1 shows a simple assembler code fragment that contains the parts of this framework. A
doubleslash (//) precedes comments about instructions.

Listing 1. Assembler code fragment
 HELLO CSECT
     USING *,15                   //Make R15 and HELLO point to the current address where
                                      //this instruction is present
        SAVE 14,12,12(13)      //Save contents in R14,R12 into address location
                               //pointed to by (12+R13) R14, and R12 holds the return
 address
                               //(the address of the next instruction to be run in the
                               //calling program)
        LR 12,15                        //Load register R12 with contents of R15
        USING HELLO,12
        WTO 'Hello world.'         //Display ‘Hello world’ on console
        XR 15,15                       //Ex-or to clear R15
        RETURN (14,12)                 //Restore the contents of R14 and R12
        END




Converting assembler to COBOL: A few tips
COBOL uses a different framework. Here are some tips to follow when converting assembler code
to COBOL:


         Declare variables in the DIVISION under WORKING-STORAGE SECTION.

         Code logic in the PROCEDURE DIVISION.

         Ignore a USING statement.

         Map DSECT (dummy section) declarations as linkage section variables.

         Replace register names, such as R1 and R2, with meaningful names in COBOL.
         When copying or moving blocks of data from one memory location to another using
          COBOL, use the pointer concept. The pointer concept replaces the LOAD and STORE

          instructions of assembler. Declare a pointer as 01 PTR1 USAGE IS POINTER.

         Change MODE statements in assembler to if-else conditions in COBOL.

         Do not explicitly code DS-Declare Storage for variables in COBOL; it is automatically
          handled during variable declaration.

The code from Listing 1 is converted to COBOL in Listing 2.

Listing 2. Assembler code fragment rewritten in COBOL
           IDENTIFICATION DIVISION.
           PROGRAM-ID. HELLO.
           ENVIRONMENT DIVISION.
           DATA DIVISION.
           PROCEDURE DIVISION.
           MAIN-PARA.
                            DISPLAY 'Hello world'.
                            STOP RUN.




Code samples: Converting assembler to COBOL
Listing 3 shows part of a sample assembler routine called ASSEM123, and Listing 4 shows its
equivalent in COBOL code. The routine creates a copy of a certain memory range (<1K) and
copies a 1K chunk of data into another program-defined area. This process repeats until the entire
block of data >1K is copied to the program-defined area. This is a called routine with parameters
passed to it.
Note that comments to the code are surrounded by asterisks (**) or preceded by double slashes
(//).

Listing 3. Assembler routine code sample ASSEM123
 ASSEM123 CSECT
          STM    R14,R12,12(R13)          SAVE REGS
          BALR   R12,0                    ESTABLISH BASE REGISTER
          USING *,R12
          ST     R13,WKAREA+4
          LA     R13,WKAREA
         SPACE   3
         L       R6,0(R1)                   ESTABLISH ADDR TO BEG OF W-S
         USING   WSSTRT,R6
         L       R5,4(R1)                   ESTABLISH ADDR TO END OF W-S
         USING   WSEND,R5
         L       R8,8(R1)                   ESTABLISH ADDR TO W-S SAVE AREA
         USING   WSSAVE,R8
         L       R4,12(R1)                  ESTABLISH ADDR TO W-S PARM LIST
         USING   WSPARM,R4
         MVI     DONEFLG,NOTDONE            SET FLAG TO NOT DONE
         LR      R7,R5                          PREPARE FOR SUBTRACTION
         SR      R7,R6                          DETERMINE LENGTH OF W-S
         AH      R7,ONE                 FOR CORRECT LENGTH, SET UP 1
         CH      R7,FULLREC        BIGGER THAN THE 1K SAVE REC
         BH      MRECS                  NEED TO STORE MULTIPLE SAVE RECS
         LR      R9,R7                      SET UP FOR 1 MOVE AND SAVE
         STH     R7,0(R8)                SET LENGTH IN SAVE REC
         LA      R8,2(R8)                 BUMP TGT PTR PAST LENGTH 1/2WORD
         MVCL    R8,R6                  MOVE WS TO WS SAVE REC
         MVI     DONEFLG,DONE            SET FLAG TO DONE
         B       FINISH                    EXIT
MRECS    DS      0H
         CLC     SAVER6,=F'00'           FIRST TIME THROUGH?
         BE      FIRST                            R6 OK AS IS, MUST MOVE MAX LRECL
         L       R6,SAVER6                   LOAD PTR TO NEXT WS AREA TO MOVE
         LR      R7,R5                            R5 POINTS TO WS END, CALC
         SR      R7,R6                            DETERMINE LENGTH OF WS TO MOVE
         AH      R7,ONE                      SET UP 1 FOR PROPER LENGTH
         CH      R7,FULLREC             REMAINING WS <= SAVE REC SIZE?
         BNH     CONT1                     YES...MOVE ACTUAL WS LENGTH
FIRST    LH      R7,FULLREC        NO...LOAD MAX REC SIZE
CONT1    LR      R9,R7                   LOAD ODD RECS WIH MOVE LENGTH
         STH     R7,0(R8)                    SET LENGTH IN SAVE REC
         LA      R8,2(R8)                     BUMP TGT PTR PAST LENGTH
         MVCL    R8,R6                   MOVE WS TO WS SAVE REC
         AR      R6,R7                   BUMP SOURCE PTR BY MOVE LENGTH
         ST      R6,SAVER6               SAVE FOR NEXT CALL
         CR      R6,R5                   MOVED ALL WS?
         BL      FINISH                  NOT YET...EXIT
         MVI     DONEFLG,DONE            SET FLAGE TO DONE
         B       FINISH                  AND EXIT
         EJECT
FINISH   DS      0H
         XR      R15,R15                    ZERO TO RETURN CODE REG
         L       R13,WKAREA+4               RESTORE BACK PTR
         LM      R14,R12,12(R13)            RESTORE REGS
         BR      R14                        RETURN TO CALLER
         SPACE   3

//Defining all the variables used in the assembler routine
WKAREA DS        18F                        REG SAVE AREA
FULLREC DC       H'0998'                    MAX REX SIZE FOR WS SAVE REC
ONE     DC       H'0001'                    MAX REX SIZE FOR WS SAVE REC
        SPACE    1
NEWSLEN DC       F'00000000'                NEW WS LENGTH SAVE AREA
WSACUM DC        F'00000000'                OLD WS ACCUMULATOR ON RESTORE
WTOMSG WTO         'U0001-** RSAM ABEND -   CHANGE IN WORKING STORAGE SIZE',X
                 ROUTCDE=11,MF=L
         SPACE   1

//Here 4 DSECTS are given that correspond to 4 parameters
//sent to the corresponding COBOL code
//(these are captured in the LINKAGE SECTION of the COBOL code)
WSSTRT   DSECT                              WORKING-STORAGE START ADDR
         DS      F
WSEND    DSECT                              WORKING-STORAGE END ADDR
         DS      F
WSSAVE   DSECT                              WORKING-STORAGE SAVE RECORD
         DS      F
WSPARM   DSECT                              WORKING-STORAGE SAVE MODE
         MODE        DS   CL1
          SAVER6 DS         F                 R6 SAVE AREA
          DONEFLG DS        CL1               TELLS IF ALL OF WS WAS MOVED


 DONE    EQU      C'D'                         DONE MOVE
 NOTDONE EQU      C'N'                         NOT DONE MOVE
 ERROR   EQU      C'E'                         WS LENGTH HAS CHANGED ON RESTART
         SPACE    1
 R1      EQU      1                            PARAMETER LIST ADDRESS
 R3      EQU      3                            WORK REGISTER
 R4      EQU      4                            PARAMETER LIST ADDRESS
 R5      EQU      5                            PARAMETER LIST ADDRESS
 R6      EQU      6                            W-S PARM ADDR
 R7      EQU      7                            W-S START ADDR
 R8      EQU      8                            W-S END ADDR
 R9      EQU      9                            W-S SAVE RECORD ADDR
 R10     EQU      10                           SAVE REG FOR W-S START ADDR
 R11     EQU      11
 R12     EQU      12                           MODULE BASE REG
 R13     EQU      13
 R14     EQU      14                           LINK REGISTER
 R15     EQU      15                           BRANCH REGISTER
         SPACE    3
         END

Because the assembler routine is a called routine, a driver program is simulated to test the COBOL
equivalent. This driver passes the four parameters to the COBOL code equivalent to the ones used
in the assembler routine. Listing 4 shows that the driver passes a 1K chunk of data named WS-

DISPAREA to the equivalent COBOL code.

Listing 4. Assembler driver program code fragment
         IDENTIFICATION DIVISION.
         PROGRAM-ID. DRIVER1.
         ENVIRONMENT DIVISION.
         DATA DIVISION.
         WORKING-STORAGE SECTION.
          01 WS-PTR1 USAGE POINTER.
          01 WS-PTR2 USAGE POINTER.
          01 WS-INDEX PIC 9(2) VALUE ZEROS.
          01 WSSAVE-PARM-AREA.
                05 WSSAVE-PARM PIC X VALUE 'S'.
                05 WSSAVE-INDEX PIC S9(8) COMP SYNC VALUE +0.
                05 WSSAVE-RETURN-CODE PIC X VALUE 'N'.
          01 WSSAVE-R POINTER.
         LINKAGE SECTION.
          01 WS-DISPAREA PIC X(1000)
         PROCEDURE DIVISION USING WS-DISPAREA.
         MAIN-PARA.
 //SETS THE POINTERS TO THE START AND END OF WS-DISPAREA .HERE
 //ADDRESSABILITY IS GIVEN TO THESE POINTER VARIABLES BY POINTING
 //IT TO WS-DISPAREA.WS-DISPAREA SHOULD ALWAYS BE DEFINED IN THE
 //LINKAGE SECTION ELSE AN ADDRESSABILITY ERROR WILL BE SHOWN
                  SET WS-PTR1 TO ADDRESS OF WS-DISPAREA.
                  SET WS-PTR2 TO ADDRESS OF WS-DISPAREA(999:1)
                  CALL PGM1 USING WS-PTR1
                                                      WS-PTR2
                                                      WSSAVE-PARM-AREA
                                                      WSSAVE-R.
                  END-CALL.
                  STOP RUN.

Listing 5 shows the assembler code from Listing 4 converted to COBOL. Note that the driver
program with the four parameters calls PGM1, the COBOL code equivalent to that used in the
assembler routine. The length of the data passed is calculated and then copied into a program-
defined area.

Listing 5. Assembler routine code sample ASSEM123 rewritten in COBOL
IDENTIFICATION DIVISION.
  PROGRAM-ID. PGM1.
  ENVIRONMENT DIVISION.
  DATA DIVISION.

  WORKING-STORAGE SECTION.
  01 WORK-RECORD PIC X(100) VALUE SPACES.
  01   SUBSCR PIC 9(5) VALUE ZERO.
  01   LOOP-COUNTER PIC 9(5) VALUE ZERO.
  01   WS-REMAINDER PIC 9(5) VALUE ZERO.
  01   LOOP-EXIT PIC 9(1) VALUE ZERO.
  01   WS-LENGTH PIC 9(5) VALUE ZERO.
  01   WS-IDX PIC 9(5) VALUE 1.
  01   WS-IDX2 PIC 9(5) VALUE 1.
  01   WS-POINTER POINTER.

  LINKAGE SECTION.
  01 START-ADDRESS-POINTER POINTER.
  01 END-ADDRESS-POINTER POINTER.

  01 WS-END PIC X(1).
  01 WS-PARM.
     05 WS-PARM1 PIC X.
     05 WS-INDEX1 PIC S9(8) COMP SYNC.
     05 WS-RETURN-CODE PIC X.

  01 WS-AREA.
     05 MY-ARRAY PIC X(1) OCCURS 1000 TIMES.
  01 WSSAVE-R1.
     05 WSSAVE-R12 PIC X(1) OCCURS 100 TIMES.

  PROCEDURE DIVISION USING START-ADDRESS-POINTER
                           END-ADDRESS-POINTER
                           WS-PARM
                           WSSAVE-R1.
  MAIN-PARA.
 IF WS-PARM1 EQUAL 'S' AND WS-RETURN-CODE EQUAL 'N'

        DISPLAY 'START-ADDRESS-POINTER=' START-ADDRESS-POINTER
        DISPLAY 'END-ADDRESS-POINTER=' END-ADDRESS-POINTER

      SET ADDRESS OF WS-AREA TO START-ADDRESS-POINTER
      DISPLAY 'WS-AREA=' WS-AREA
      SET ADDRESS OF WS-END TO END-ADDRESS-POINTER
*******************************************************************
//BLOCK TO CALCULATE THE LENGTH OF THE WORKING-STORAGE
//SECTION PASSED
*******************************************************************
     PERFORM UNTIL LOOP-EXIT = 1
         IF MY-ARRAY ( WS-IDX ) NOT = WS-END
            COMPUTE
                  WS-LENGTH = WS-LENGTH + 1
            END-COMPUTE
         ELSE
            SET WS-POINTER TO ADDRESS OF MY-ARRAY(WS-IDX)
            IF WS-POINTER = END-ADDRESS-POINTER
                MOVE 1 TO LOOP-EXIT
            END-IF
            COMPUTE
                WS-LENGTH = WS-LENGTH + 1
            END-COMPUTE
         END-IF
         ADD 1 TO WS-IDX
     END-PERFORM

      DISPLAY 'LENGTH OF AREA PASSED=' WS-LENGTH
********************************************************************
//COPIES THE WORKING-STORAGE SECTION PASSED VIA WS-DISPAREA
//OF THE DRIVER INTO WS-AREA. FROM WS-AREA, DATA IS COPIED TO
//WORK RECORD AND FROM WORK-RECORD TO THE WSSAVE-R12
//ARRAY, WHICH IS 100 BYTES LONG. WORK RECORD ALSO HOLDS
//ONLY 100 BYTES OF DATA THUS TRANSFERRING THE DATA TO
//WSSAVE-R12
********************************************************************


      DIVIDE WS-LENGTH BY 100 GIVING LOOP-COUNTER
                               REMAINDER WS-REMAINDER
      END-DIVIDE
      MOVE 1 TO SUBSCR
      PERFORM LOOP-COUNTER TIMES
         MOVE WS-AREA(SUBSCR:100) TO WORK-RECORD
         DISPLAY 'WORK-RECORD=' WORK-RECORD
         MOVE WORK-RECORD TO WSSAVE-R12(WS-IDX2)
          COMPUTE
              SUBSCR = SUBSCR + 10
         END-COMPUTE
         COMPUTE
              WS-IDX2 = WS-IDX2 + 10
         END-COMPUTE
      END-PERFORM
      IF WS-REMAINDER NOT = ZERO
         MOVE WS-AREA(SUBSCR:WS-REMAINDER) TO
              WORK-RECORD
         MOVE WORK-RECORD TO WSSAVE-R12(WS-IDX2)
      END-IF
END-IF.

MOVE 'D' TO WS-RETURN-CODE.
DISPLAY WS-RETURN-CODE.
EXIT PROGRAM.

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:48
posted:5/21/2010
language:English
pages:7