Retrieving EXEC statement PARM Data & the EX instruction



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

Retrieving EXEC statement PARM Data & the EX instruction

Postby steve-myers » Sat Jun 30, 2012 8:58 am

The following code shows the start of a program that retrieves PARM data from a JCL EXEC statement, an illustrates the use of the EX instruction. In this program, PARM data is a 1 to 4 byte string containing EBCDIC decimal digits. Bad data is simply ignored.
LOCKDS   CSECT                     DEFINE PROGRAM CSECT
         USING *,12                ESTABLISH PROGRAM ADDRESSABILITY
         SAVE  (14,12),,*          SAVE REGISTERS
         LR    12,15               COPY ENTRY POINT ADDR TO REG 12
         LA    15,SAVEAREA         LOAD ADDR OF A NEW SAVE AREA
         ST    15,8(,13)           ADD NEW SAVE AREA
         ST    13,4(,15)            TO THE SAVE AREA CHAIN
         LR    13,15               ESTABLISH NEW SAVE AREA POINTER
         LHI   10,50               PRESET DEFAULT COUNT
         L     3,0(,1)             LOAD ADDR OF PARM
         LH    15,0(,3)            LOAD LENGTH
         LTR   15,15               TEST LENGTH
         BNP   NOPARM              BR IF NO PARM TEXT
         CHI   15,4                TEST LENGTH
         BH    NOPARM              BR IF TOO LONG
         BCTR  15,0                REDUCE LENGTH BY 1 FOR HARDWARE
         EX    15,NUMTRT           VERIFY PARM TEXT IS NUMERIC
         BNZ   NOPARM              BR IF NOT
         EX    15,NUMPACK          CONVERT PARM TEXT TO PACKED DECIMAL
         CVB   10,16(,13)          CONVERT PACKED DECIMAL TO BINARY
NOPARM   DC    0H'0'
         ...
NUMTRT   TRT   2(*-*,3),TESTNUM
NUMPACK  PACK  16(8,13),2(*-*,3)
         ...
SAVEAREA DC    9D'0'               72 BYTE OS/360 SAVE AREA
TESTNUM  DC    0XL256'0',(C'0')X'04',10X'00',(256-(*-TESTNUM))X'04'
The first part of the program saves the caller's registers into the caller provided save area, and prepares a new save area.

When a program is entered from JCL, register 1 points to a parameter list. The parameter list, in turn, points to the EXEC statement PARM data preceded by a two byte binary length.

L 3,0(,1)
LH 15,0(,3)

The L instruction loads the address of the parameter data from the parameter list, then the LH instruction loads the number of bytes of PARM data.

LTR 15,15
BNP NOPARM
CHI 15,4
BH NOPARM

First, the program tests if there is any parameter data. If the parameter length is 0, there is no data. The program then tests if the length is longer than the program will process. The UNPK instruction can actually handle 16 bytes, but the program imposes an arbitrary max length of 4 bytes.

BCTR 15,0

The BCTR instruction subtracts 1 from the length. Part of the reason the program bypasses this instruction if there is no parameter data is because this instruction will produce -1, or X'FFFFFFFF' in the register if the register contains 0 before the BCTR instruction executes, and that will cause problems later. The program does the subtraction because data length values in instructions like TRT and UNPK is always 1 less than the data length the instruction processes.

With the encoded data length in register 15, the program translates the decimal digits to binary. First, though, we want to verify the data is decimal digits.

EX 15,NUMTRT
BNZ NOPARM
...
NUMTRT TRT 2(*-*,3),TESTNUM
...
TESTNUM DC 0XL256'0',(C'0')X'04',10X'00',(256-(*-TESTNUM))X'04'

The EX instruction is a little complicated. It loads a single instruction from storage, updates the second byte of the instruction by ORing the low order 8 bits of the register specified , and then executes the modified instruction as thoughit were an instruction just fetched from storage.

The TRT instruction is also complicated: working from left to right in the table specified by the first operand - the parameter text - it loads a byte of data from the second table calculated by adding the contents of the byte in the first table to the address of the second table. Let's say the byte contains 5, or X'F5', so it loads the byte at TESTNUM+X'F5'. Each byte in the second table is called a "function byte." If the function byte is X'00', the instruction continues with the next byte in the first table. If the function byte is not X'00', the instruction stops, sets a condition code, and stores the address in the table where it found the byte with a non-zero function byte into register 1, and stores the non-zero function byte into the low order 8 bits of register 2. Our program is only interested in the condition code; it does not care about the registers.

The TESTNUM table is a complicated Assember DC instruction that actually contains 4 data elements, one after the other.

0XL256'0' -- This does not generate any data, but it seems to say that 256 bytes of Assembler type X are present.

(C'0')X'04' -- This generates 240 non-zero function bytes that correspond to non-decimal digit EBCDIC codes. The (C'0') is a count using the value of the EBCDIC 0. Doing it this way means that if the value for C'0' should ever change, all we have to do is assemble the program and the table will be adjusted appropriately.

10X'00' -- This generates 10 function code bytes that correspond to the EBCDIC codes for 0 through 9.

(256-(*-TESTNUM))X'04' -- This fills out the table with 6 more non-zero function bytes. However, if the value for the EBDIC 0 should ever change, the count calculated by (256-(*-TESTNUM)) will effectively change and the table will be built correctly.

If we made it this far, we are certain we have PARM text containing valid decimal digits. All we have to do is translate the digits to a binary value.

EX 15,NUMPACK
CVB 10,16(,13)

The conversion is done in two steps. The EX instruction executes a PACK instruction that converts the decimal digits to their correspond packed decimal data area. Rather than define a separate 8 byte data area the program uses 8 bytes in the new save area that do not presently contain any data. This is safe because once these 8 bytes have been converted to binary there is no further need for the data. The EX instruction works the same as it did for the TRT instruction. If we look at the initial value for NUMPACK, we have
0000D4 F270 D010 3002 00010 00002   638 NUMPACK  PACK  16(8,13),2(*-*,3)
The 0000D4 is the offset of the NUMPACK instruction. F2 is the machine operation code for UNPK. 70 is the length - 1 of the first operand area, and the "length" of the second operand. The contents of register 15 - the length of the parameter text - 1 is ORed into this byte to provide the second operand length. D010 is the base register and displacement of the first operand, from the instruction, and 3002 is the base register and displacement of the second operand.

CVB 10,16(,13)

The CVB instruction translates the 8 byte packed decimal number to binary.

These users thanked the author steve-myers for the post:
Peter_Mann (Sat Jul 21, 2012 2:24 am)
steve-myers
Global moderator
 
Posts: 2105
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 243 times

Re: Retrieving EXEC statement PARM Data & the EX instruction

Postby sensuixel » Fri Jul 20, 2012 12:22 am

As usual, crystal clear explanation.
I've never seen such method to validate the value of parm fields.

Thanks you ;)
sensuixel
 
Posts: 58
Joined: Mon Feb 21, 2011 8:55 pm
Has thanked: 0 time
Been thanked: 0 time

Re: Retrieving EXEC statement PARM Data & the EX instruction

Postby steve-myers » Fri Jul 20, 2012 2:44 am

There are two parts here: retrieving the PARM data and validating it. The validation you do depends on the definition of the data, 1 to 4 decimal numeric digits in this case, and this method applies to any data field containing 1 to 4 decimal digits. A different definition implies a different validation method. Many PARM field definitions are PARM=''keyword,keyword,...,keyword' which requires much different code than the very simple validation scheme used here.
steve-myers
Global moderator
 
Posts: 2105
Joined: Thu Jun 03, 2010 6:21 pm
Has thanked: 4 times
Been thanked: 243 times


Return to Assembler

 


  • Related topics
    Replies
    Views
    Last post