A Sample Program

This lecture will focus on a sample program that was assigned for all students
to execute on the mainframe.  This program is run under the IBM operating
system called OS (as opposed to DOS), which is tailored for large installations.

Please note that the IBM mainframe operating system DOS is not related to that
once used on small computers.  The latter, often called “DOS” is really MSDOS,
the Microsoft Disk Operating System.

This lecture contains both code fragments and annotations on those code fragments.
Code fragments will be presented in the font Courier New (bold), as follows.

         SAVE  (14,12)

All other material will be in the standard font Times New Roman, as is this sentence.

The student will recall that the input to the assembler is not free–form; column placement
is extremely important.  Your instructor discovered this fact when an otherwise correct
program would not assembly correctly.

 


Column Conventions in the Assembler Program

The column conventions are as follows:

        Columns 1 – 8         The name or label of the statement or declarative

        Column 9                        This must be blank

        Columns 10 – 14     The operation: instruction, declarative, or macro

        Column 15              This must be blank

        Columns 16 – 71     The operands for the operation.
                                        Any continuation line must begin in column 16.

        Column 72              If nonblank, the next line is a continuation of this one.

Consider the following example, taken from the sample program.

PRINTER  DCB   DDNAME=PRINTER,                                         X

               DSORG=PS,                                               X

               DEVD=DA,                                                X

               MACRF=(PM),                                             X

               LRECL=133,                                              X

               RECFM=FM                                                

The label PRINTER is placed in columns 1 – 7

The DCB macro is placed in columns 10 – 12

The arguments are placed in columns 16 – 71, the continuation mark is in column 72.

More on Column Conventions

Were we to use the COLS command in the editor, we would see the following
for the first line of the statement above.

PRINTER  DCB   DDNAME=PRINTER,                                         X

000000000111111111122222222223333333333444444444455555555556666666666777

123456789012345678901234567890123456789012345678901234567890123456789012

Coding forms

It used to be common practice to have coding forms with the columns clearly indicated.
On such a form, the DCB statement might appear as follows, except that the form would
have been used by a human; thus the text would have been hand written.

We shall discuss the meaning (semantics) of this statement in a later slide.
At the moment, the only point is to emphasize the importance of proper column
alignment.


Column 1

Here are the rules for use of column 1 in the assembler.  Note, that we are not speaking
of
the first non–blank entry in a column, but column 1.  Consider the following, with
the columns displayed above the operation and operands

0000000001111111111222222
1234567890123456789012345
         AR    R1,R2    ADD REGISTR R2 TO R1

Note that column 1 contains a blank.  Column 10 is the first non–blank column.

If column 1 contains an “*”, the entire line is treated as a comment.

0000000001111111111222222
1234567890123456789012345
* THIS ENTIRE LINE IS A COMMENT

If column 1 contains an alphabetical character, it is the start of a label.  The label
continues from column 1 up to the first blank column or column 9.

0000000001111111111222222
1234567890123456789012345
ADD2    AR    R1,R2    Label is ADD2


Some Common Errors

Consider the following two examples.  The first is correct; the second is not.

0000000001111111111222222
1234567890123456789012345
         AR    R1,R2    ADD REGISTR R2 TO R1

This one should work as advertised.  Note that the first blank space after the expected
operands marks the start of an in–line comment.  Now consider the following.

0000000001111111111222222
1234567890123456789012345
AR    R1,R2    ADD REGISTR R2 TO R1

Here the two characters “AR” are taken as the label, because the “A” is in column 1.

The assembler attempts to interpret “R1” as an operation, and fails.

How about this one, which is also incorrect.

0000000001111111111222222
1234567890123456789012345
         AR    R1, R2    ADD REGISTR R2 TO R1

Here the problem is the space after “R1,”.  The string “R2” is taken as starting
the comment field.  Because of the space, it is not an operand.


Comments in the Style of Java

High–level languages, such as Java and C++, allow in–line comments.

Consider the following two examples.

0000000001111111111222222
1234567890123456789012345
         AR    R1,R2    ADD REGISTR R2 TO R1

0000000001111111111222222
1234567890123456789012345
         AR    R1,R2    //ADD REGISTR R2 TO R1

In the first example, the comment is “ADD REGISTR R2 TO R1”.

In the second example, the comment is “//ADD REGISTR R2 TO R1”;
it just has two extra characters.

It is the blank column that introduces the comment, not the “//”.

IMPORTANT NOTE: Many job control statements begin with “//”.

These are NOT comments, but an essential part of the program.

 


Job Control Statements

In order to understand the structure of the sample program, one must imagine a “batch
job”, which is a sequence of cards submitted to the computer.

Your input file comprises a sequence of lines of text.  Each line of text should be
viewed as a “card image”, basically eighty characters with some of them blanks.

Here is the job control language from my submission of the program.

//CSU0003A JOB (ASSY),'ED BOZ',CLASS=A,MSGCLASS=A,            

// NOTIFY=&SYSUID,MSGLEVEL=(0,1)                              

//ASM      EXEC PROC=HLLASMCLG                                

//SYSIN    DD *                                                

Each student should employ a unique job name based on the user ID (mine is obviously
CSU0003).  The job name is the seven character User ID with a single letter appended.
It appears that the letter can be arbitrary and need not be changed.

The HLLASMCLG directive seems to direct the assembler to “compile, load, and go”;
that is, to execute the code generated.

The SYSIN DD* directive indicates that the input for the assembler will be found
in the lines of text just following.


Assembly Language Source: Part 1

The first two lines of the code contain macros, which expand to pre–defined sequences
of code that direct the execution of the assembler.

         TITLE  'ED B - FROM SKELETON ASSEMBLER PROGRAM'  

         PRINT  ON,NODATA,NOGEN                            

The TITLE macro provides a title at the top of each page of the listing.
Note the single quotes at the start and end of the text to be displayed.

The PRINT macro specifies the format of the assembly listing.

    ON                The program listing is printed.

    NODATA     Restricts the display of the binary machine language equivalent
                          of each assembler statement to 16 hexadecimal digits.

    NOGEN        Suppresses the generation of the statements to which a macro
                          will expand.  In general, a macro will expand into about ten statements.
                          With this option, only the macro itself is listed.

We shall later want to use the GEN option when we study macro writing.
This will allow us to examine the code expansions of our macros.


Assembly Language Source: Part 2

The next section of the code includes comments.

Each comment of this form begins with an “*” in the first column.

While not required, the use of comments is good programming practice.
This set of comments is about the minimal that is useful.

****************************************************************

*                                                              

*   PROGRAMMER:  EDWARD BOSWORTH, COLUMBUS STATE UNIVERSITY    

*   ASSIGNMENT:  FIRST LAB ASSIGNMENT FOR CPSC 3121            

*   DATE      :  JANUARY 21, 2009                              

*   COMMENTS  :  THIS ALLOWS THE STUDENT TO LEAN HOW TO ENTER  

*             :  A PROGRAM ON THE MAINFRAME AND EXECUTE IT.    

*                                                              

****************************************************************

 


Assembly Language Source: Part 3

An Equate directive is used to equate one symbol with another.  In the code that follows
each occurrence of “R0” will be replaced by “0”, each “R1” by “1”, etc.  Use of these
symbols allows register references to become visible in the program listings.

****************************************************************

*     REGISTER EQUATES                                         

****************************************************************

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                                               

****************************************************************


Assembly Language Source: Part 4

This block of code is the standard “start up” code used at the beginning of any
program to be run on the Mainframe.  This code should be viewed as “boilerplate”.

The form of this code block suggests that the code is that for a subprogram: either a
subroutine or a function.  Indeed, that is the way the Operating System handles the
execution of any program: it is a subprogram of the Operating System.

**************************************************************

LAB1     CSECT                                               

         SAVE  (14,12)             SAVE THE CALLER'S REGISTERS

         BALR  R12,0               ESTABLISH                 

         USING *,R12               ADDRESSABILITY            

         LA    R2,SAVEAREA         ADDRESS OF MY SAVE AREA   

         ST    R2,8(,R13)          FORWARD CHAIN MINE        

         ST    R13,SAVEAREA+4      BACKWARD CHAIN CALLER'S   

         LR    R13,R2              SET 13 FROM MY SUB CALLS  

**************************************************************

The first line LAB1    CSECT is a declaration of a Control Section, named “LAB1”.

By definition, a control section is “a block of coding that can be relocated (independent
of other coding) without altering the operating logic of the program”. 

Practically, a control section is just one block of assembly code.


 

Opening the Input and Output

As indicated, the next section of code opens the input and output and prints a header
line to the output.  Unlike the book’s example, this does not skip to a new page.

*  SET UP THE INPUT AND OUTPUT AND PRINT HEADERS                

*                                                                

         OPEN (PRINTER,(OUTPUT))  OPEN THE STANDARD OUTPUT       

         OPEN (FILEIN,(INPUT))    OPEN THE STANDARD INPUT       

         PUT PRINTER,PRHEAD       PRINT HEADER                  

         GET FILEIN,RECORDIN      GET THE FIRST RECORD, IF THERE

*                                                               

The first two statements open a device, called PRINTER, for output and another,
called
FILEIN, for input.

Note that the open of the input and the output can be combined into a single statement.

         OPEN (FILEIN,(INPUT), PRINTER,(OUTPUT))

Your instructor prefers to use separate statements, one for each I/O file.
This facilitates isolation of execution errors associated with the OPEN statements.

The definition of FILEIN, given later in a Data Control Block, specifies the label of a
statement to be executed when an End–of–File occurs on the input.


The Print Loop

Here is the “main body” of the assembly code.

         GET FILEIN,RECORDIN          GET THE FIRST RECORD  

*                                                           

*  READ AND PRINT LOOP                                      

*                                                           

A10LOOP  MVC DATAPR,RECORDIN          MOVE INPUT RECORD     

         PUT PRINTER,PRINT            PRINT THE RECORD      

         GET FILEIN,RECORDIN          GET THE NEXT RECORD   

         B A10LOOP                    GO BACK AND PROCESS   

*                                                            

Note that the code at label A10LOOP is executed the first time only if the top line
of code has actually returned a record (“card image” or 80 characters of text).

On execution of this code at label A10LOOP, we are guaranteed that there is a record
in the data storage area associated with the identifier
RECORDIN.

These eighty characters of text (trailing blanks are included) are copied into the data
storage area associated with the identifier
DATAPR, and then sent to the output.

This code then tries to get another line (card image) of input.  If there is more input,
the code executes an unconditional branch to the statement
A10LOOP, thus
continuing the loop.  Otherwise, it branches to
A90END and closes the program.

The Print Loop (Java Style)

The best way to view this print loop is to add a construct that is used
in both Java and C/C++.

         GET FILEIN,RECORDIN          GET THE FIRST RECORD  

*                                                           

A10LOOP  MVC DATAPR,RECORDIN          MOVE INPUT RECORD     

         PUT PRINTER,PRINT            PRINT THE RECORD      

         GET FILEIN,RECORDIN          GET THE NEXT RECORD   

         If End_of_File Then Break

         B A10LOOP                    GO BACK AND PROCESS   

*                                                            

The loop is never entered if the first GET statement does not return a record.

The loop is exited when the contained GET statement encounters an End of File.
Otherwise, the processing continues.

Again, the Data Control Block for the input device, FILEIN, specifies the label
of the statement to be executed when an EOF is found on the input.


Closing the Input and Output

When there is no more input to process, the code calls a section to close the I/O
and terminate the processing.

A90END   CLOSE FILEIN                                         

         CLOSE PRINTER                                        

Note the statement with label A90END.  This will be seen to be the statement associated
with the end of file on the input. 

Traditionally, a program will have some “close up” processing to do at this time, such as
printing totals and summaries.  Here the code just closes the Input and Output.

This is the end of the custom code.  The rest of the code is “boilerplate”.

 


The Standard Closing Code

Here is the standard “postfix code”.  It must be the last section of code executed in any
program to be run on our mainframe, which is running the IBM OS operating system.

*******************  END LOGIC    ************************** 

         L     R13,SAVEAREA+4          POINT AT OLD SAVE AREA

         LM    R14,R12,12(R13)         RESTORE THE REGISTERS 

         LA    R15,0                   RETURN CODE = 0       

         BR    R14                 RETURN TO OPERATING SYSTEM

**************************************************************

When your program terminates, it must execute a return to the Operating
System so that the latter can continue execution of another program. 

This is the return code required by the operating system.

 


Defining the Output

The output file is defined using a standard DCB (Data Control Block)

PRINTER  DCB   DSORG=PS,                                               X

               MACRF=(PM),                                             X

               DEVD=DA,                                                X

               DDNAME=PRINTER,                                         X

               RECFM=FM,                                               X

               LRECL=133                                               

The output is to a PS (Physical Sequential) device.

The specific unit happens to be a disk file, which supports DA (Direct Access)

The name associated with this is PRINTER.  The label is obviously used here with
two distinct meanings.  I shall investigate this.

The logical record length is 133 bytes, for 133 characters.

Note the continuation indicators in column 72 of each line but the last.

These six lines are assembled as one statement.

This is the example of invocation of a macro by keywords; each line is of the
form KEYWORD=VALUE.


Defining the Input

The input file is defined using a standard DCB (Data Control Block).

FILEIN   DCB   DSORG=PS,                                               X

               MACRF=(GM),                                             X

               DEVD=DA,                                                X

               DDNAME=FILEIN,                                          X

               EODAD=A90END,                                           X

               RECFM=FB,                                               X

               LRECL=80                                                 

DSORG indicates that the data set is “physical sequential”, organized as
a sequence of input records and not indexed in any way.

MACRF defines the type of input operation, here “get and move to work area”,
so that it can be accessed by the GET macro.

DDNAME identifies the file’s symbolic name.

DEVD defines a particular I/O unit.  This data set is Direct Access.

RECFM specifies the operation to move data from the work area.

LRECL specifies the length of a logical record.  It is 80 bytes for 80 characters.

EODAD provides the end–of–file address for the input file that is read sequentially.


The Input Data Record

RECORDIN reserves eighty bytes of memory storage for use in the input of an
eighty–character card image.
  All input will be assumed to be eighty characters.

*************************************************************

*    INPUT RECORD AREA                                       

*************************************************************

RECORDIN DS    CL80                                         

*************************************************************

Future programs will follow a convention familiar to COBOL programmers. 

We shall still assume 80–column input, but divide it into fields.

RECORDIN DS    0CL80  THE CARD HAS 80 COLUMNS
FIRSTNME DS    CL8    FIRST 8 COLUMNS FOR THE FIRST NAME
LASTNME  DS    CL10   NEXT 10 COLUMNS FOR THE LAST NAME

ACCOUNT  DS    CL12   NEXT 12 COLUMNS FOR THE ACCOUNT NUM
FILLER   DS    CL50   OTHER 50 COLUMNS ARE PROBABLY BLANK.

Note the “0” in the “0CL80” that defines the entry RECORDIN.

Each card image must correspond to 80 bytes for 80 characters.

The “0CL80” does not actually allocate any space, but serves almost as a comment that
the next 80 bytes are associated with input.  The next 4 statements allocate the 80 bytes.


Sample Input Data Record: Reading Positive Integers

Suppose that we wanted to read a list of five–digit numbers, one number per “card”.
Each digit is represented as a character, encoded in EBCDIC form.

The appropriate declaration might be written as follows.

RECORDIN DS    0CL80  THE CARD HAS 80 COLUMNS

DIGITS   DS     CL5   FIVE BYTES FOR FIVE DIGITS

FILLER   DS     CL75  THE NEXT 75 COLUMNS ARE IGNORED.

In this, the first five columns of each input line hold a character to be interpreted as a
digit.  The other 75 are not used.  This input is not free form.

Based on the above declaration, one would characterize the first five columns as follows:


Sample Code and Data Structure

Consider the code fragment below, containing operations not yet defined.  This
uses the above declarations, specifically the first five columns as digits.

         PACK PACKIN,DIGITS    CONVERT TO PACKED DECIMAL

         AP   PACKSUM,PACKIN   ADD TO THE SUM.

Given the definition of DIGITS, the PACK instruction expects the input to be
right justified in the first five columns.  The input below will be read as “23”.

   23     Note the three spaces before the digits.
          2 is in the tens column and 3 is in the units.

The following input is not proper for this declaration.

  37      “3” in column 3, “7” in column 4, column 5 blank.

The PACK instruction will process the first five columns, and result in a number that
does not have the correct format.  The
AP (an addition instruction) will fail because its
input does not have the correct input, and the program will terminate abnormally.


The Output Data Area: The Header

The header is an example of a constant record to be output.

***************************************************************

*                                                             

*      HERE IS THE HEADER FOR SPRING 2009                      

*                                                             

***************************************************************

PRHEAD DS   0CL133                                            

PRC1   DC    C' '             PRINT CONTROL:PRINT ON NEXT LINE

       DC    CL10' '                                          

       DC    CL122'***COLUMBUS STATE UNIVERSITY SPRING 2009***'

*                                                             

***************************************************************

The blank in the first character will cause normal spacing when the line is printed.

Optionally, one can have double spaced lines, overprinted lines, etc.

The next ten columns in the header output will contain blanks.

The next 122 columns will contain the text, padded to the right with blanks.

 


The Output Data Area: Print Area

Card image data is transferred to this area and then printed.

The function of this program is to read data cards and print them.

***************************************************************

*                                                             

*      THIS DEFINES THE PRINT OUTPUT AREA.                    

*      IT BEGINS WITH A BLANK PRINT CONTROL CHARACTER         

*      IT THEN HAS 80 CHARACTERS TO HOLD THE INPUT CARD IMAGE 

*      IT THEN HAS 42 CHARACTERS OF FILLER.                   

*                                                             

PRINT  DS   0CL133              PRINT AREA                    

PRC2   DC    C' '               PRINT CONTROL CHARACTER       

       DC    CL10' '                                          

DATAPR DC    CL80' '                                          

       DC    CL42' '                                          

*                                                              

***************************************************************

The area labeled DATAPR, holding 80 bytes, is for the card image data.

Each card image will be printed with normal spacing and ten blanks at the
start of the line.

The decision to place ten spaces before the echoed input is arbitrary.


The Register Save Area and Literal Pool

The program must have local storage sufficient to hold the registers
that the Operating System will save when the program is called. 

The size of the area is exactly 18 full–words.

****************************************************************

*                                                              

*    REGISTER SAVE AREA                                        

*                                                               

****************************************************************

SAVEAREA DS  18F                                               

****************************************************************

The program must specify an area in which the assembler can store the literals it
generates as a result of a certain kind of immediate argument in the code.

The LTORG macro identifies the location at which the literal pool is to start.

****************************************************************

*                                                              

*    LITERAL POOL - THIS PROGRAM DOES NOT USE LITERALS.        

*                                                              

****************************************************************

*        LTORG *                                               

The LTORG must be used if the program uses any literals.


More on the Literal Pool

The LTORG macro identifies the location at which the literal pool is to start.  It
must be used if the program contains any reference to literals. 

The way to use this is to “uncomment” the LTORG line, so that it appears as follows.

****************************************************************

*                                                               

*    LITERAL POOL – THE ASSEMBLER PLACES LITERALS HERE.        

*                                                              

****************************************************************

         LTORG *                                                

Note that I have changed the comment to reflect the fact that the program
does use literals.

Consider the following line of assembly language source code,
which uses literals.

         L R4,=F‘17’  Register 4 gets the value 17.

The assembler will allocate a full word in the literal pool, give it the value 17
and the label
=F‘17’.


The End of the Job

These are the last cards in the “job deck”.

         END LAB1                                               

/*                                                              

//GO.PRINTER DD SYSOUT=*                                       

//GO.FILEIN DD *                                               

LINE 1 SPRING 2009                                             

LINE 2 SPRING 2009                                             

LINE 3 SPRING 2009                                             

LINE 4 SPRING 2009                                             

/*                                                             

The two statements form the end of the assembly language source code.

         END LAB1                                              

/*                                                             

The next two lines are directives to the operating system to define the real I/O devices.
The second line specifies that the input is to be taken from the lines that immediately
follow.  The data for input are found on the next four lines.

The last line is the end of the job.