Let's take a look at a minimal data set copy program.
MCOPY CSECT Define program CSECT
USING *,12 Establish program addressability
SAVE (14,12),,* Save registers
LR 12,15 Prepare program vase register
LA 15,SAVEAREA Compute new save area address
ST 15,8(,13) Add new save area to the
ST 13,4(,15) save area chain
LR 13,15 Prepare new save area pointer
OPEN (INDCB,INPUT,OUTDCB,OUTPUT) Open the data sets
COPYLOOP GET INDCB Read an input record
LR 0,1 Copy the record address to reg 0
PUT OUTDCB,(0) Write the output record
B COPYLOOP Do it again
EOF CLOSE MF=(E,CPARM) Close the data sets
LA 2,CPARM Load address of the parameter list
CLL0100 L 1,0(,2) Load a DCB address
* N 1,=A(X'FFFFFF') Isolate the 24-bit DCB address
FREEPOOL (1) Free the buffer pool
TM 0(2),X'80' End of the parameter list?
LA 2,4(,2) Compute address of next DCB pointer
BZ CLL0100 Br if not end of the parameter list
L 13,4(,13) Load address of the higher save area
RETURN (14,12),T,RC=0 Restore registers & return
CPARM CLOSE (INDCB,,OUTDCB),MF=L
INDCB DCB DSORG=PS,MACRF=GL,DDNAME=INPUT,EODAD=EOF
OUTDCB DCB DSORG=PS,MACRF=PM,DDNAME=OUTPUT
SAVEAREA DC 18F'0'
DC 0D'0'
LTORG ,
DC 0D'0'
END MCOPY
USING *,12 Establish program addressability
SAVE (14,12),,* Save registers
LR 12,15 Prepare program vase register
LA 15,SAVEAREA Compute new save area address
ST 15,8(,13) Add new save area to the
ST 13,4(,15) save area chain
LR 13,15 Prepare new save area pointer
OPEN (INDCB,INPUT,OUTDCB,OUTPUT) Open the data sets
COPYLOOP GET INDCB Read an input record
LR 0,1 Copy the record address to reg 0
PUT OUTDCB,(0) Write the output record
B COPYLOOP Do it again
EOF CLOSE MF=(E,CPARM) Close the data sets
LA 2,CPARM Load address of the parameter list
CLL0100 L 1,0(,2) Load a DCB address
* N 1,=A(X'FFFFFF') Isolate the 24-bit DCB address
FREEPOOL (1) Free the buffer pool
TM 0(2),X'80' End of the parameter list?
LA 2,4(,2) Compute address of next DCB pointer
BZ CLL0100 Br if not end of the parameter list
L 13,4(,13) Load address of the higher save area
RETURN (14,12),T,RC=0 Restore registers & return
CPARM CLOSE (INDCB,,OUTDCB),MF=L
INDCB DCB DSORG=PS,MACRF=GL,DDNAME=INPUT,EODAD=EOF
OUTDCB DCB DSORG=PS,MACRF=PM,DDNAME=OUTPUT
SAVEAREA DC 18F'0'
DC 0D'0'
LTORG ,
DC 0D'0'
END MCOPY
The answer is that old problem: storage. In 1964 and 1965, when OS/360 was designed and implemented, storage was very expensive. One byte of storage cost roughly one US dollar. The dreamers that were marketing System/360 had the dream that there would be one operating system for all systems. The engineers building what became OS/360 used every trick they could imagine to cut OS/360's footprint. One of the tricks was to use the high order byte of a full word used as an address for other data. For example -
2 OPEN (ADCB,OUTPUT),MF=L
000000 3+ DC 0F'0'
000000 8F 4+ DC AL1(143)
000001 000000 5+ DC AL3(ADCB)
6 CLOSE (ADCB,LEAVE),MF=L
000004 7+ DC 0F'0'
000004 B0 8+ DC AL1(176)
000005 000000 9+ DC AL3(ADCB)
000000 3+ DC 0F'0'
000000 8F 4+ DC AL1(143)
000001 000000 5+ DC AL3(ADCB)
6 CLOSE (ADCB,LEAVE),MF=L
000004 7+ DC 0F'0'
000004 B0 8+ DC AL1(176)
000005 000000 9+ DC AL3(ADCB)
The DCB repeated this. There are many addresses in the DCB. With one exception – not used until MVS/XA and OS/390 – all these addresses use the high order byte for something else. For example -
00002C 00 31+ DC BL1'00000000' BFTEK,BFLN,HIARCHY
00002D 00000A 32+ DC AL3(EOF) EODAD
00002D 00000A 32+ DC AL3(EOF) EODAD
Another trick in the DCB was to not assemble unused data areas. For example -
11 ADCB DCB MACRF=E,DDNAME=EXCPDD
14+* DATA CONTROL BLOCK
15+*
000028 00028 00000 16+ ORG *-40 TO ELIMINATE UNUSED SPACE
000000 17+ADCB DS 0F'0' ORIGIN ON WORD BOUNDARY
000000 00000 00028 18+ ORG *+40 TO ORIGIN GENERATION
20+* FOUNDATION BLOCK
000028 C5E7C3D7C4C44040 22+ DC CL8'EXCPDD' DDNAME
000030 02 23+ DC BL1'00000010' OFLGS
000031 00 24+ DC BL1'00000000' IFLG
000032 8000 25+ DC BL2'1000000000000000' MACR
14+* DATA CONTROL BLOCK
15+*
000028 00028 00000 16+ ORG *-40 TO ELIMINATE UNUSED SPACE
000000 17+ADCB DS 0F'0' ORIGIN ON WORD BOUNDARY
000000 00000 00028 18+ ORG *+40 TO ORIGIN GENERATION
20+* FOUNDATION BLOCK
000028 C5E7C3D7C4C44040 22+ DC CL8'EXCPDD' DDNAME
000030 02 23+ DC BL1'00000010' OFLGS
000031 00 24+ DC BL1'00000000' IFLG
000032 8000 25+ DC BL2'1000000000000000' MACR
The little copy program at the start of the post runs fine as an AMODE 24, RMODE 24 program. It takes two changes to run AMODE 31, RMODE 24:
- Add an AMODE 31 Assembler statement. It can be linked AMODE 31 without the statement, but it won't run.
- Remove the * from the N 1,=A(X'FFFFFF') statement. This statement removes the CLOSE macro option, leaving the 24-bit DCB address. A wise programmer always uses this statement, so the same technique is used for both an AMODE 24 and an AMODE 31 program.
In a few days I will post the little copy program revised to run RMODE ANY.