We can use the Assembler to do the heavy lifting for us.  It is assumed the reader knows the basics of writing, assembling and executing assembler programs.

We are really writing two programs here.  One is the 80-80 list program and the other is a program to create the IPL deck.  When we assemble and run our program only half of the code will be executed – the other half will be punched into a card deck.

We can make use of the ORG Assembler directive to make our work easier.  ORG is not an executable instruction.  It is an instruction to the assembler telling it how to organize storage.   Our first card in the IPL deck is the 24 bytes containing the PSW and two CCWs.  We can get the assembler to help us create it by using:

CARD0    DS    80XL1'00'
         ORG   CARD0
IPLPSW   DC    X'00',X'00',X'0000',X'00',AL3(1024)
CCW1     DC    X'02',AL3(512),X'60',X'00',AL2(80)
CCW2     DC    X'08',AL3(512),X'00',X'00',AL2(0)
         ORG   ,

First we create an area of 80 bytes of hex zeros.  We can then use ORG to reset the address back to the beginning of the card area.  This will cause the 80 bytes of zeros to be overlayed with the data for the PSW and CCWs.  After we define the PSW and CCWs we use ORG with no operand to reset the address to the highest address previously used before we reset it with the first ORG.  This keeps us from having to count bytes and manually pad out the unused portion of our 80 bytes card area.

We can create our second card containing the additional read CCWs the same way.

         DS    0D
CARD1    DC    80XL1'00'            Second IPL Card
         ORG   CARD1
*
CCW3     DC    X'02',AL3(1024),X'60',x'00',AL2(80)
CCW4     DC    X'02',AL3(1024+80),X'60',X'00',AL2(80)
CCW5     DC    X'02',AL3(1024+160),X'20',X'00',AL2(80)
*
         ORG   ,

The third, fourth and fifth cards of our IPL deck come from the code of our executable program.

Here is the program to punch out our IPL deck:

CARD80   CSECT ,
         STM   R14,R12,12(R13)      Save callers registers
         LR    R12,R15              Use R12 as our program base
         USING CARD80,R12
*
         LA    R1,SAVEA             Point to new Save Area
         ST    R1,8(,R13)           Chain
         ST    R13,4(,R1)                On
         LR    R13,R1                      Save Area
*
         OPEN  (PUNCH,OUTPUT)       Open Output File
*
         PUT   PUNCH,CARD0          Write First Card
*
         PUT   PUNCH,CARD1          Write Second Card
*
* Write Three Cards of Executable Code
*
         PUT   PUNCH,CARD2
         PUT   PUNCH,CARD2+80
         PUT   PUNCH,CARD2+160
*

The way I know to punch three cards for the executable code is simple.  I assembled the program and then looked at the listing to determine the size in bytes of the IPL program.  It was then a simple matter of dividing by 80 and adding one for any nonzero remainder to get the number of cards required.

At this point, we have written five cards that contain our IPL stand alone program, and if we were working with real cards, we would be done, because we would just put some data cards behind our IPL deck after it was punched out and then input the combined deck via the card reader. However, since we are working with virtual cards rather than real ones that we already have on hand, we must also create the data cards we will use for our testing.

To do this, we will generate ten additional data cards. Our first step will be to fill an entire card image with 80 instances of a certain character, and then we will overlay the first three card columns of this card image with a number from 01 to 10, followed by a space. Thus, our first data card will look like the following.

 

01 *****************...

Here is the code I use to create my data cards.

         LA    R3,10          Number of times to repeat
         LA    R4,=C'01020304050607080910'
         LA    R5,=C'*+@#$%-() '
LOOP     DS    0H
         MVC   BUF(1),0(R5)   Move in char to repeat
         MVC   BUF+1(79),BUF  Fill buffer with repeated char
         MVC   BUF(2),0(R4)   Move in card number
         MVI   BUF+2,C' '     Followed by a space
*
         PUT   PUNCH,BUF      Write out card record
*
         LA    R4,2(,R4)      Point to next card number
         LA    R5,1(,R5)      Point to next repeating character
         BCT   R3,LOOP        Loop back for next card image
*

Now we are almost done creating the card deck and we can close the DCB, restore the caller’s registers and exit our program.

         CLOSE (PUNCH)         Close output DCB
*
         L     R13,4(,R13)     Point to caller's save area
         LM    R14,R12,12(R13) Restore caller's registers
         SLR   R15,R15         Set RC=0
         BR    R14             Return to caller
*

All we are missing is some data areas which we now add, as follows.

         LTORG ,               Generate literals here
*
BUF      DS    CL80            Output Buffer
*
SAVEA    DS    18F             Register Save Area
*
PUNCH    DCB   DSORG=PS,MACRF=PM,BLKSIZE=80,LRECL=80,
               RECFM=F,DDNAME=PUNCH
*
*
         DROP  R12              No longer used as a base register

[Next – Card80 Assembly Listing ]