Retrieve JCL PARM properly



High Level Assembler(HLASM) for MVS & VM & VSE

Re: Retrieve JCL PARM properly

Postby sensuixel » Tue Feb 22, 2011 9:21 pm

stevexff wrote:The EX instruction allows you to execute another out-of-line instruction (like an MVC for example), overriding the length field with the contents of a register. This allows you do a MVC where the length is not known until run time, like the length of your PARM field. steve-myers has worked around this by using MVCL, which also allows you to specify the length in a register, and works just as well as long as you happen to have four registers to spare; this isn't always the case :)


Il like the idea of working on variable length, I definitely try with an EX instruction.
sensuixel
 
Posts: 58
Joined: Mon Feb 21, 2011 8:55 pm
Has thanked: 0 time
Been thanked: 0 time

Re: Re: Retrieve JCL PARM properly

 

Re: Retrieve JCL PARM properly

Postby steve-myers » Tue Feb 22, 2011 11:59 pm

The EX instruction is definitely useful, but there are some issues.
  • When it is used with with a register, the low order 8 bits of the register are ORed with the second 8 bits of the instruction that is executed; they do not replace those bits. when I put together my little GETPARM program, I thought of using EX to copy the parameter text to my data area, but then I realized I wanted to use the blank fill provided by MVCL.
  • Most SS instructions use a length value that is one byte less than the actual length, so if you are moving 8 bytes with a MVC instruction, the actual length value in the MVC instruction is 7. The Assembler does this automatically, but a user of EX must adjust the value in the register before issuing the EX instruction.
steve-myers
Global moderator
 
Posts: 1885
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 197 times

Re: Retrieve JCL PARM properly

Postby steve-myers » Wed Feb 23, 2011 2:30 am

enrico-sorichetti wrote:... any half decently written prolog/entry macro will restore the R1 content to its original value !

Agreed, but in my career I've seen any number of variations on this theme, and most of them were pretty half baked.

One problem is the programmer is forced into whatever convention the author of the macro wants at the time. I see six immediate issues with this INITL macro
  • What text string is used for the program ID?
  • Is the text string constructed properly and in the "right" place? Most INITL type macros fail this test in one way or another.
  • Where is the save area? At a guess, it is embedded in the macro expansion, which is sort of OK, but it is not a solution I have ever favored.
  • Since the save area is embedded in the INITL macro expansion, the program is not reenterable and cannot be made reenterable.
  • Is the new save area correctly and completely connected to the save area chain.
  • What is the relationship of the base register to the start of the program. I personally prefer that they are equal so that the offset in the instruction matches the program offset, but given that the save area is part of the macro, you've given away a significant chunk of potential addressability, which I don't always like.
This issue about conventions is more complex than most beginners realize. When I started in the late 1960s, the usual convention for a reenterable program is the save area started addressability for the work area. The Language Environment DSA concept still follows this convention, and its entry and exit macros follow this convention. By the middle 1970s I realized this idea was not so good, and I no longer use it.

One dirty secret us Assembler programmers seldom think about is "standard" linkage is pretty poor.
000000                00000 001A3     1 GETPARM  CSECT
                 R:C  00000           2          USING *,12
                                      3          SAVE  (14,12),,*
000000 47F0 F00C            0000C     5+         B     12(0,15)
000004 07                             6+         DC    AL1(7)
000005 C7C5E3D7C1D9D4                 7+         DC    CL7'GETPARM'
00000C 90EC D00C            0000C     8+         STM   14,12,12(13)
000010 18CF                           9          LR    12,15
000012 41F0 C0E0            000E0    10          LA    15,SAVEAREA
000016 50F0 D008            00008    11          ST    15,8(,13)
00001A 50D0 F004            00004    12          ST    13,4(,15)
00001E 18DF                          13          LR    13,15

Part of the problem is the instruction prefetching done by modern hardware. Hopefully it's smart enough to stop when it gets to the B instruction, but that just slows things down. In addition, since the B instruction uses a base register, it's hard for the hardware to know where to resume its instruction prefetch. Yes, you can persuade the SAVE macro to use a BRC 15,*+12 instruction in place of the B instruction, but few beginners (much less us old dinosaurs) know the method, which should make it easier for the hardware to know where to resume its instruction prefetch.

The STM instruction is quite fast, but it still saves too many registers. By using register 4 as the base register (registers 5 through 12 would not be used, so why save them? This varies by program, ...) we could improve this, and by improving this we also need to restore fewer registers, so that helps improve exiting from the program.
steve-myers
Global moderator
 
Posts: 1885
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 197 times

Re: Retrieve JCL PARM properly

Postby steve-myers » Wed Feb 23, 2011 8:54 am

One more issue about program linkage. One occasionally sees the BAKR (Branch and Stack) instruction used in place of the SAVE macro and the PR instruction to restore registers and return. Years ago, long before 64-bit registers, I did some performance testing and found it was very poor, and it has only gotten worse. On Z hardware the BAKR instruction saves 16 64-bit registers and 16 32-bit access registers, and the PR instruction restores all of it. You can't trick it into saving less. Of course, BAKR does not have the issue about instruction prefetch I grumbled about with the standard SAVE macro, and it does not have the issue that sometimes the SAVE macro saves too little, which I did not mention before.
steve-myers
Global moderator
 
Posts: 1885
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 197 times

Re: Retrieve JCL PARM properly

Postby steve-myers » Wed Feb 23, 2011 11:16 am

stevexff wrote:... steve-myers has worked around this by using MVCL, which also allows you to specify the length in a register, and works just as well as long as you happen to have four registers to spare; this isn't always the case :)
True, but regs 14, 15, 0 and 1 are often available when other registers are blocked up. In addition, with some thought you can use 14 and 15, or 0 and 1 for two of the registers, and just need 2 other registers, which often makes MVCL practical. The usual prohibition about using register 0 as an address does not apply with MVCL and CLCL.

I usually use locate mode QSAM for input, but seldom use it for output; the penalty for misusing it for output is quite severe.
steve-myers
Global moderator
 
Posts: 1885
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 197 times

Re: Retrieve JCL PARM properly

Postby steve-myers » Thu Feb 24, 2011 10:05 am

GETPARM program changes to
  • Use "locate" mode PUT to write the output
  • Use the EX instruction to execute an MVC instruction to copy the parameter text to the output buffer.
         L     2,0(,1)             LOAD ADDRESS OF PARM DATA
         OPEN  (ADCB,OUTPUT)       OPEN THE DCB
         LH    3,0(,2)             LOAD LENGTH OF PARM DATA
         LTR   3,3                 TEST LENGTH OF PARM DATA
         BNZ   WRITEREC            BR IF PARM DATA PRESENT
         LA    2,ERRTEXT-2         LOAD ADDRESS OF ERROR TEXT
         LA    3,L'ERRTEXT         LOAD LENGTH OF ERROR TEXT
WRITEREC STH   3,DCBLRECL          STORE THE RECORD LENGTH
         PUT   ADCB                GET BUFFER SPACE FOR THE OUTPUT     X
                                    RECORD
         BCTR  3,0                 REDUCE LENGTH BY 1
         EX    3,COPYPARM          COPY THE PARAMETER TEXT TO THE      X
                                    OUTPUT BUFFER
         CLOSE ADCB                CLOSE THE DCB
         ...
COPYPARM MVC   0(*-*,1),2(2)    ** EXECUTE ONLY **
ADCB     DCB   DSORG=PS,MACRF=PL,RECFM=U,BLKSIZE=100,DDNAME=SYSPRINT
ERRTEXT  DC    C'THERE IS NO PARM DATA!'
There is one potential issue in this code. If register 3 is 0 when the BCTR instruction executes, register 3 will become -1, or X'FFFFFFFF'. This won't happen in this code snippet because reg 3 was previously checked for 0 (no parm data, in other words), and loaded with a non-zero value, the length of the error message. The PUT macro stores the address of the output buffer in register 1.
steve-myers
Global moderator
 
Posts: 1885
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 197 times

Previous

Return to Assembler

 


  • Related topics
    Replies
    Views
    Last post