Dealing with programs bigger than 4K
This time I will discuss how to make a program bigger than 4096 bytes which is the limitation of one base register.
PGM5 CSECT
PGM5 RMODE ANY
ENTRY PGM5
STM 14,12,12(13)
BASR 11,0
START DS 0H
USING START,11
MVC WTOTEXT,=CL70'HELLO WORLD'
B WTO
WTOTEXT_LGD DC Y(L'WTOTEXT)
WTOTEXT DS CL70
DC 4096C' ' ⇐ This is my way to increase the the size
WTO DS 0H
WTO TEXT=WTOTEXT_LGD,ROUTCDE=11
LM 14,12,12(13)
RETURN RETURN RC=0
LTORG
END
PGM5 BINDER
END
|
When I assemble the source above, I get a serious problem. Experienced programmers will recognize it but not with joy. We've all tried to solve this problem for hours on end after normal work hours.
000000 00000 01136 2 PGM5 CSECT
3 PGM5 RMODE ANY
4 ENTRY PGM5
000000 90EC D008 00008 5 STM 14,12,12(13)
000004 0DB0 6 BASR 11,0
000006 7 START DS 0H
R:B 00006 8 USING START,11
000006 0000 0000 0000 00000 00000 9 MVC WTOTEXT,=CL70'HELLO WORL
** ASMA034E Operand =CL70'HELLO WORLD' beyond active USING range by 235 bytes
** ASMA435I Record 9 in EXJEL.EXJEL005.JOB07575.D0000101.? on volume:
00000C 0000 0000 00000 10 B WTO
** ASMA034E Operand WTO beyond active USING range by 83 bytes
** ASMA435I Record 10 in EXJEL.EXJEL005.JOB07575.D0000101.? on volume:
000010 0046 11 WTOTEXT_LGD DC Y(L'WTOTEXT)
000012 12 WTOTEXT DS CL70
000058 4040404040404040 13 DC 4096C' '
001058 14 WTO DS 0H
001058 A715 003A 010CC 15 WTO TEXT=WTOTEXT_LGD,ROUTCDE
0010E0 98EC D008 00008 54 LM 14,12,12(13)
0010E4 41F0 0000 00000 55 RETURN RETURN RC=0
0010F0 60 LTORG
0010F0 C8C5D3D3D640E6D6 61 =CL70'HELLO WORLD'
62 END
|
I will give you two ways to solve it, a quick and dirty and a more structured approach.
Several base registers
We are essentially in need for one more base register and we can actually add one more so we can span over 8K instead of 4K. I add register 10 as a new register so the program has 10 and 11 as its base registers. Register 10 addresses the first 4096 bytes and register 11 the rest.
I will explain how to do that by explaining each line. We start at line 5
5. Load current address into register 10
6. Just a label that is not used
7. Then we load register 10 into register 11 and adds 4095 (X’FFF’) to register 11
8. Add one to register 11 because one base register can span over 4096 bytes
9. The USING tells the assembler to use both registers as base register.
6. Just a label that is not used
7. Then we load register 10 into register 11 and adds 4095 (X’FFF’) to register 11
8. Add one to register 11 because one base register can span over 4096 bytes
9. The USING tells the assembler to use both registers as base register.
PGM5 CSECT
PGM5 RMODE ANY
ENTRY PGM5
STM 14,12,12(13)
BASR 10,0
START DS 0H
LA 11,X'FFF'(,10)
LA 11,1(,11)
USING START,10,11
MVC WTOTEXT,=CL70'HELLO WORLD'
B WTO
WTOTEXT_LGD DC Y(L'WTOTEXT)
WTOTEXT DS CL70
DC 4096C' '
WTO DS 0H
WTO TEXT=WTOTEXT_LGD,ROUTCDE=11
LM 14,12,12(13)
RETURN RETURN RC=0
LTORG
END
PGM5 BINDER
END
|
Source of PGM5 that has two base registers
If you are now in the first half of the program and you branch to the other half, the branch will use register 11 and visa versa. Take a look at location counter 000014. The WTO label is in the second half of the program so register 11 is used.
Loc Object Code Addr1 Addr2 Stmt Source Statement
1 PRINT NOGEN
000000 00000 0113E 2 PGM5 CSECT
3 PGM5 RMODE ANY
4 ENTRY PGM5
000000 90EC D00C 0000C 5 STM 14,12,12(13)
000004 0DA0 6 BASR 10,0
000006 7 START DS 0H
000006 41B0 AFFF 00FFF 8 LA 11,X'FFF'(,10)
00000A 41B0 B001 00001 9 LA 11,1(,11)
R:AB 00006 10 USING START,10,11
00000E D245 A014 B0F2 0001A 010F8 11 MVC WTOTEXT,=CL70'HELLO WORL
000014 47F0 B05A 01060 12 B WTO
000018 0046 13 WTOTEXT_LGD DC Y(L'WTOTEXT)
00001A 14 WTOTEXT DS CL70
000060 4040404040404040 15 DC 4096C' '
001060 16 WTO DS 0H
001060 A715 003A 010D4 17 WTO TEXT=WTOTEXT_LGD,ROUTCDE
0010E8 98EC D00C 0000C 56 LM 14,12,12(13)
0010EC 41F0 0000 00000 57 RETURN RETURN RC=0
0010F8 62 LTORG
0010F8 C8C5D3D3D640E6D6 63 =CL70'HELLO WORLD'
64 END
|
Assembler list of PGM5 with two base registers
Separating your program into subrutines
If you are a clever programmer you will probably always separate your assembler program into subroutines. That makes it easier to understand and maintain. I will show you an example where I separated the above program into two CSECTs. You do not need to code the CSECT but I like it because it shows that I am serious about it. You are now not allowed to branch between CSECTs. You would not do that anyway but an ignorant programmer, that might want to maintain your program, would try and you have now prohibited him from destroying your architecture.
I use register 11 in both CSECTs. I can do that because I save all registers on entry to CSECT WTO_HW and reload them right before returning to the caller. WTO_HW has actually become a small program which the Binder (Linkage Editor) links together with PGM5 into a load module. At the end of each CSECT I “DROP” register 11 as base register. Again that is in order to tell the assembler that the USING goes till here and no further. Again a good practise.
PGM5 CSECT
PGM5 RMODE ANY
PGM5 AMODE 31
ENTRY PGM5
STM 14,12,12(13)
BASR 11,0
USING *,11
LA 1,SAVEAREA
ST 1,8(,13)
ST 13,4(,1)
LR 13,1
L 15,=A(WTO_HW)
BASR 14,15
L 1,4(,13)
LM 14,12,12(1)
RETURN RETURN RC=0
SAVEAREA DS 18F
LTORG
DC 4096C' '
DROP 11
********************************************
WTO_HW CSECT
STM 14,12,12(13)
BASR 11,0
USING *,11
MVC WTOTEXT,=CL70'HELLO WORLD'
WTO TEXT=WTOTEXT_LGD,ROUTCDE=11
LM 14,12,12(13)
BR 14
WTOTEXT_LGD DC Y(L'WTOTEXT)
WTOTEXT DS CL70
LTORG
DROP 11
END
PGM5 BINDER
END
|
PGM5 is now well structured
Loc Object Code Addr1 Addr2 Stmt Source Statement
1 PRINT NOGEN
000000 00000 01074 2 PGM5 CSECT
3 PGM5 RMODE ANY
4 PGM5 AMODE 31
5 ENTRY PGM5
000000 90EC D00C 0000C 6 STM 14,12,12(13)
000004 0DB0 7 BASR 11,0
R:B 00006 8 USING *,11
000006 4110 B022 00028 9 LA 1,SAVEAREA
00000A 5010 D008 00008 10 ST 1,8(,13)
00000E 50D0 1004 00004 11 ST 13,4(,1)
000012 18D1 12 LR 13,1
000014 58F0 B06A 00070 13 L 15,=A(WTO_HW)
000018 0DEF 14 BASR 14,15
00001A 5810 D004 00004 15 L 1,4(,13)
00001E 98EC 100C 0000C 16 LM 14,12,12(1)
000022 41F0 0000 00000 17 RETURN RETURN RC=0
000028 22 SAVEAREA DS 18F
000070 23 LTORG
000070 00001078 24 =A(WTO_HW)
000074 4040404040404040 25 DC 4096C' '
26 DROP 11
27 ***************************************
001078 01078 0012E 28 WTO_HW CSECT
001078 90EC D00C 0000C 29 STM 14,12,12(13)
00107C 0DB0 30 BASR 11,0
R:B 0107E 31 USING *,11
00107E D245 B096 B0E2 01114 01160 32 MVC WTOTEXT,=CL70'HELLO WORLD'
001084 A715 003A 010F8 33 WTO TEXT=WTOTEXT_LGD,ROUTCDE =11
00110C 98EC D00C 0000C 72 LM 14,12,12(13)
001110 07FE 73 BR 14
001112 0046 74 WTOTEXT_LGD DC Y(L'WTOTEXT)
001114 75 WTOTEXT DS CL70
001160 76 LTORG
001160 C8C5D3D3D640E6D6 77 =CL70'HELLO WORLD'
78 DROP 11
79 END
|
The assembler list of PGM5.
Location 00107E shows that register 11 is a new base register with a new value.
By the way. Please, never use large work areas or constants in your program. It will give you problems with your base registers and your load module will be huge and take up space in the loadlib. Getmain your work area or, if it is constants, either use an assemble table or read them from an external medium.Next time, I will show a more modern way to solve the problem.