I am updating our standard entry/exit macros to support AMODE 64, and support various types of AMODEs and ASCs on entry. As a part of this, I've had to add some more LOCTRs to the definition of our work areas. But let me demonstrate this little trap for you:
WORK DSECT ,
WORKLOC1 LOCTR ,
DW10 DS D
WORKLOC2 LOCTR ,
DW20 DS D
WORKLOC1 LOCTR ,
DW11 DS D
WORKLOC2 LOCTR ,
DW21 DS D
WORKLOC1 LOCTR ,
DW13 DS D
* All done!
WORKLEN EQU *-WORK
LHI R0,WORKLEN
STORAGE OBTAIN,LENGTH=(0)
What value is loaded into R0 by the LHI instruction, and how many bytes of storage will be obtained? Raise your hand. How many say 40? OK, a couple. How many say 24? Aha, those are the ones who have worked with LOCTR and have been bit by this little gotcha.
Those of you who said 40, can you figure it why it's 24? Yep, that's right. I'll go ahead and redo the above with location counters, so the reason becomes clear:
00000000 WORK DSECT ,
00000000 WORKLOC1 LOCTR ,
00000000 DW10 DS D
00000018 WORKLOC2 LOCTR ,
00000018 DW20 DS D
00000008 WORKLOC1 LOCTR ,
00000008 DW11 DS D
00000020 WORKLOC2 LOCTR ,
00000020 DW21 DS D
00000010 WORKLOC1 LOCTR ,
00000010 DW13 DS D
* All done!
00000018 WORKLEN EQU *-WORK
The EQU is in WORKLOC1, and it correctly calculates the length of the WORKLOC1 LOCTR area. There are two ways to correct this: 1) insert a WORKLOC2 LOCTR before the equate; 2) my preferred solution, which is to introduce a new LOCTR (call it WORK_END) before the EQU. In either case, WORKLEN will now be the actual length of the WORK DSECT, 40 bytes.
LOCTR is very powerful, as it allows you to define items in macros but yet segregate; such as putting required constants in a CONSTANT LOCTR area, out of the instruction pipeline. But, like any powerful tool in the system developer's arsenal, it must be used with great caution, and always take a sanity look at the assembler listing. The hour of debugging you save may be your own!
And a few more things...
- Please try to avoid hard-coded offsets. It may have made sense to the person who originally wrote this code 20 years ago, but when someone new comes along, having nice, identifiable labels and DSECTs will make that person's life easier when trying to decipher your control block chaining. The time you spend coding the DSECT and labels now may preserve someone's sanity down the road.
- When you do switch to DSECTs, remember to put the right register in the USING statement. (That's more of a *headdesk* moment for me.)
- Don't use PRINT OFF unless you really need it. Nothing ticks me off more that looking at a listing file and seeing that the entry macro has issued PRINT OFF, and nothing follows.