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.
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