Joined: 26 Apr 2022 Posts: 9 Location: United States
Hi,
After 30+ years as a MF Storage Admin, working for clients and vendors, I am trying to learn z/OS Assembler. I am in a program thru Marist College with IBM and I'm struggling with some basic stuff. I appreciate the help I received yesterday on another assignment. I really don't want to abuse the generosity of the members here.
I spent several days on this assignment, then stepped away to do another. This assignment involves loading a table and then we're to (a) output the bit notation for each byte and (b) output the hex representation of each byte.
Code:
* DEFINE TABLE FWRDS
FWRDS DC 0F
DC X'00FF00FF'
DC X'ABCDEF01'
DC X'FFFFFFFF'
DC X'00000000'
DC X'AAAAAAAA'
DC X'33333333'
DC X'12345678'
DC X'FFFFFFFF' USE AS END OF TABLE
*
FWRDSEND EQU * GET CURRENT ADDRESS
FWRDLEN EQU FWRDSEND-FWRDS SUBTRACT ADDRESS OF FWRDS FROM FWRDSEND
NOWRDS DC A(FWRDLEN/4) DIVIDE BY 4 TO GET # OF FULL WORDS
I am trying to use a DSECT for each byte:
OUT08 DSECT USED FOR ASSINGING VALUES FOR BITS IN A BYTE
OUTBYTE DS 0CL8 OUTPUT BYTE
OUTBIN0 DS CL1 OUTPUT BIT 0 OF 8
OUTBIN1 DS CL1 OUTPUT BIT 1 OF 8
OUTBIN2 DS CL1 OUTPUT BIT 2 OF 8
OUTBIN3 DS CL1 OUTPUT BIT 3 OF 8
OUTBIN4 DS CL1 OUTPUT BIT 4 OF 8
OUTBIN5 DS CL1 OUTPUT BIT 5 OF 8
OUTBIN6 DS CL1 OUTPUT BIT 6 OF 8
OUTBIN7 DS CL1 OUTPUT BIT 7 OF 8
*
* HEXOUT8 DSECT
* HEXBYTE DS 0CL8 OUTPUT BYTE IN HEX
* HEXOUT0 DS CL2 OUTPUT BIT 0 OF 8
* HEXOUT1 DS CL2 OUTPUT BIT 1 OF 8
* HEXOUT2 DS CL2 OUTPUT BIT 2 OF 8
* HEXOUT3 DS CL2 OUTPUT BIT 3 OF 8
* HEXOUT4 DS CL2 OUTPUT BIT 4 OF 8
* HEXOUT5 DS CL2 OUTPUT BIT 5 OF 8
* HEXOUT6 DS CL2 OUTPUT BIT 6 OF 8
* HEXOUT7 DS CL2 OUTPUT BIT 7 OF 8
In the CSECT I have:
Code:
* -------------------------------------------------------------------
* ESTABLISH BIT MASKS
BIT0MASK EQU B'10000000'
BIT1MASK EQU B'01000000'
BIT2MASK EQU B'00100000'
BIT3MASK EQU B'00010000'
BIT4MASK EQU B'00001000'
BIT5MASK EQU B'00000100'
BIT6MASK EQU B'00000010'
BIT7MASK EQU B'00000001'
* -------------------------------------------------------------------
* START PROCESSING LOOP
*
* -------------------------------------------------------------------
WORDCNT SR R9,R9
NEWWORD EQU *
MVC TESTWORD,FWRDS
CLC TESTWORD,=X'FFFFFFFF' FFFFFFFF INDICATES END OF TABLE
BE WRAPUP
*
*
*
LOADWORD EQU *
PUT FILEOUT,FWRDS
PUT FILEOUT,TESTWORD
MVC TEMPBYT0,X'40'
MVC TEMPBYT1,X'40'
MVC TEMPBYT2,X'40'
MVC TEMPBYT3,X'40'
MVC TEMPBYT0(1),TESTWORD+0
MVC TEMPBYT1(1),TESTWORD+1
MVC TEMPBYT2(1),TESTWORD+2
MVC TEMPBYT3(1),TESTWORD+3
PUT FILEOUT,TEMPBYT0
PUT FILEOUT,TEMPBYT1
PUT FILEOUT,TEMPBYT2
PUT FILEOUT,TEMPBYT3
*
TSTBYTE0 EQU *
B TESTBITS BRANCH TO TEST BITS
TSTBYTE1 EQU *
B TESTBITS BRANCH TO TEST BITS
TSTBYTE2 EQU *
B TESTBITS BRANCH TO TEST BITS
TSTBYTE3 EQU *
B TESTBITS BRANCH TO TEST BITS
TESTBITS EQU *
TBIT0 TM TEMPBYT0,BIT0MASK TEST BYTE FOR BIT0
BNO BIT0ON
MVC OUTBIN0,ITSAZERO PUT A 0 IN THE BIT
TBIT1 TM TEMPBYT0,BIT1MASK TEST BYTE FOR BIT1
BNO BIT1ON
MVC OUTBIN1,ITSAZERO PUT A 0 IN THE BIT
TBIT2 TM TEMPBYT0,BIT2MASK TEST BYTE FOR BIT2
BNO BIT2ON
MVC OUTBIN2,ITSAZERO PUT A 0 IN THE BIT
TBIT3 TM TEMPBYT0,BIT3MASK TEST BYTE FOR BIT3
BNO BIT3ON
MVC OUTBIN3,ITSAZERO PUT A 0 IN THE BIT
TBIT4 TM TEMPBYT0,BIT4MASK TEST BYTE FOR BIT4
BNO BIT4ON
MVC OUTBIN4,ITSAZERO PUT A 0 IN THE BIT
TBIT5 TM TEMPBYT0,BIT5MASK TEST BYTE FOR BIT5
BNO BIT5ON
MVC OUTBIN5,ITSAZERO PUT A 0 IN THE BIT
TBIT6 TM TEMPBYT0,BIT6MASK TEST BYTE FOR BIT6
BNO BIT6ON
MVC OUTBIN6,ITSAZERO PUT A 0 IN THE BIT
TBIT7 TM TEMPBYT0,BIT7MASK TEST BYTE FOR BIT7
BNO BIT7ON
MVC OUTBIN7,ITSAZERO PUT A 0 IN THE BIT
PUT FILEOUT,OUTBYTE
B NEWWORD BRANCH TO NEWWORD
* ---------------------------------------------
BIT0ON EQU *
MVC OUTBIN0,ITSAONE
B TBIT1
* ---------------------------------------------
* ----------------------------
BIT1ON EQU *
MVC OUTBIN1,ITSAONE
B TBIT2
* ----------------------------
BIT2ON EQU *
MVC OUTBIN2,ITSAONE
B TBIT3
* ----------------------------
BIT3ON EQU *
MVC OUTBIN3,ITSAONE
B TBIT4
* ----------------------------
BIT4ON EQU *
MVC OUTBIN4,ITSAONE
B TBIT5
* ----------------------------
BIT5ON EQU *
MVC OUTBIN5,ITSAONE
B TBIT6
* ----------------------------
BIT6ON EQU *
MVC OUTBIN6,ITSAONE
B TBIT7
* ----------------------------
BIT7ON EQU *
MVC OUTBIN7,ITSAONE
MVC BYTE1OUT,TEMPBYTE
PUT FILEOUT,=CL80' '
PUT FILEOUT,OUTBYTE
B NEWWORD
I have a few problems, I know. I am getting an S722 but that's probably a result of not looping, not getting the next word. I can get that taken care of.
I think the more immediate problem is that I am not moving just the one byte of the word:
My intent is to move just the first byte of TESTWORD into TEMPBYT0, the second byte of TESTWORD into TEMPBYT1...and last byte of TESTWORD into TEMPBYT3.
When I do a put of the TEMPBYTx fields I see each gets the rest of the word, not just the one byte. For example, TEMPBYT2 has the last two bytes of TESTWORD, not just the 3rd byte.
I thought that defining each of the TEMPTBYTx fields as CL1 AND the MVC TEMPBYTx(1) would get just the one byte at whichever starting point.
Any help is appreciated. Thank you.
BTW, if there is anyone here located in the Fort Worth/Dallas area that might be interested in some 1:1 tutoring for a modest fee ($50/hr?) I'm willing to pay for help - tutoring, not doing the actual coding.
Too much misunderstanding of the basic concepts...
1. The macro PUT is using QSAM access method. That is, one macro PUT always sends the LRECL number of bytes to the output dataset beginning from the record starting address. So
Code:
PUT FILEOUT,OUTBYTE
will always send LRECL=80 bytes starting from address OUTBYTE, despite of the definition
Code:
OUTBYTE DS 0CL8 OUTPUT BYTE
which someone might wrongly assume to provide only 8 bytes for output.
So, one single macro PUT must be used to send the whole prepared output line (80 bytes) to the output dataset, but never - to place a part of the data in the middle of one line.
2. The conversion of a 4-bytes word to binary representation can be organized as follows
Code:
* Convert full word of data to its binary representation
L R1,input_word load content of the data word into R1
LA R2,binary_output start of binary position inside the record
LHI R3,+32 count of bits per word (always 32)
NEXTBIT EQU * start of the loop on bits in the word
MVI 0(R2),C'0' clear the bit character with '0'
LTR R1,R1 check the sign bit of R1
JNM *+8 skip next if the bit not 1 (not "minus" value)
MVI 0(R2),C'1' replace the bit character with '1'
LA R2,1(R2) shift to the next output character
SLL R1,1 shift next bit to the sign position
BCT R3,NEXTBIT continue the loop on bits within one word
* end the loop on bits
More sophisticated instructions like BXLE could be used, but with less clarity of the code.
3. The conversion of a 4-bytes word to hexadecimal representation can be organized as follows
Code:
* Convert full word of data to its hexadecimal representation
LA R1,input_word load address of the data word into R1
LA R2,hexadecimal_output
UNPK 0(9,R2),0(5,R1) unpack (4+1) bytes at R1 to 9 bytes at R2
* now XL5'abcdefghxy' unpacked to XL9'FaFbFcFdFeFfFgFhyx'
MVI 8(R2),C' ' clear extra end byte X'yx' with blank
TR 0(8,R2),HEXTRAN correct 8 of wrong hexadecimal characters
* End of hexadecimal conversion of one word
. . . . . . . . .
* define the translation table to convert bytes X'F0'-X'FF' to characters C'0'-C'F'
HEXTRAN EQU *-C'0' set virtual start of translation table
DC C'0123456789ABCDEF' real part of translation table
I guess that information may be enough for the beginning
Besides the updated methods for the hex and binary unpacking logic, I'd recommend also to redo the general logic of the code. This is the initial draft of such updates; I did not actually test it so far, just the general thoughts from my mind.
There is no input file processing added so far, because it was not clear how the input data should look like? Internal input table left in the code, for testing purposes only.
Code:
PRINT ON,NODATA,NOGEN
STRTPGM CSECT
******************************************************************
* STANDARD LINKAGE FOR 24-BIT MODE (may be SAVE macro)
* MAY NEED REVIEWING TO MATCH THE REAL PRODUCT REQUIREMENTS
******************************************************************
STM 14,12,12(R13) SAVE CALLER'S REGS
BASR R12,0 ESTABLISH
USING *,R12 ADDRESSABILITY
ST R13,SAVEAREA+4 BACK-CHAIN CALLER'S FROM MINE
LA R13,SAVEAREA POINT TO MY LOWER-LEVEL SA
******************************************************************
* OPEN (FILEIN,(INPUT))
OPEN (FILEOUT,(OUTPUT))
*
PUT FILEOUT,HEADER1 PRINT COLUMN HEADINGS
PUT FILEOUT,HEADER2 PRINT COLUMN SUBHEADINGS
* -------------------------------------------------------------------
* START INPUT PROCESSING LOOP
* -------------------------------------------------------------------
MVC OFFSET,=F'0' reset the address count
LHI R4,WORDCNT NUMBER OF WORDS TO CONVERT
LA R5,FWRDS STARTING TABLE ADDRESS
NEWWORD EQU * start the loop on input words here
*
* Convert full word of data to its hexadecimal presentation
LR R1,R5 use the address of input word from R5
LA R2,HEXOUT use the address for output value
BAS R14,CONVHEX call the HEX converter
* End of hexadecimal conversion of one word
*
* Convert full word of data to its binary presentation
LR R1,R5 use the address of input word from R5
LA R2,BINOUT use the address of the field in record
LHI R3,COL2SIZE bit count per word, from the output field
BAS R14,CONVBIN call the BIN converter
* End the conversion of bits
*
* Calculate the offset of the just converted word
LA R1,OFFSET use the address of the offset counter
LA R2,HEXADDR use the address of the field in record
BAS R14,CONVHEX call the HEX converter
* after printing the address, update its value for the next word
L R0,OFFSET old offset value
AHI R0,L'FWRDS add one word size
ST R0,OFFSET replace with the new (next) offset value
* End of offset calculation
*
PUT FILEOUT,OUTREC1 print full output line
*
LA R5,L'FWRDS(R5) SHIFT TO THE NEXT INPUT WORD
BCT R4,NEWWORD CONTINUE THE LOOP BY WORD COUNTER
* -------------------------------------------------------------------
* END INPUT PROCESSING LOOP
* -------------------------------------------------------------------
WRAPUP DS 0H PROCESSED LAST WORD ENDS HERE
***************** CLOSING ********************************************
FINAL DS 0H
* CLOSE FILEIN
CLOSE FILEOUT
*********************** STANDARD EXIT (may be RETURN macro) **********
RETURN DS 0H BRANCH TO HERE FOR NORMAL RETURN
L R13,SAVEAREA+4 POINT TO CALLER'S SAVE AREA
LM R14,R12,12(R13) RESTORE CALLER'S REGS
SR R15,R15 SET RETURN CODE REG 15 = 0
BR R14
* -------------------------------------------------------------------
* DEFINE SUBROUTINES
* -------------------------------------------------------------------
*
* Convert full word of data to its hexadecimal presentation
*
CONVHEX DS 0H
*
* INPUT PARAMETERS:
* R1 - address of the data word to unpack hex digits
* R2 - address of hexadecimal presentation output
* R14 - return address
*
UNPK 0(9,R2),0(5,R1) unpack 5 bytes at R1 to 9 bytes at R2
* now XL5'abcdefghxy' unpacked to XL9'FaFbFcFdFeFfFgFhyx'
MVI 8(R2),C' ' clear extra end byte X'yx' with blank
TR 0(8,R2),HEXTRAN correct 8 wrong characters to '0'-'F'
* end of hexadecimal conversion of one word
BR R14 return to caller
*
* -------------------------------------------------------------------
* Convert full word of data to its binary presentation
*
CONVBIN DS 0H
*
* INPUT PARAMETERS:
* R1 - address of the data word to unpack bits
* R2 - address of binary presentation output
* R3 - count of bits to convert (up to 32)
* R14 - return address
*
* R0 - used as work register
*
L R0,0(R1) get content of the data word into R0
NEXTBIT EQU * start of the loop on bits in the word
MVI 0(R2),C'0' clear the bit character with '0'
LTR R0,R0 check the sign bit of R0
JNM *+8 skip if the bit not 1 (not "minus")
MVI 0(R2),C'1' replace the bit character with '1'
LA R2,1(R2) shift to the next output character
SLL R0,1 shift next bit to the sign position
BCT R3,NEXTBIT the loop up to 32 bits within one word
* End the loop on bits
BR R14 return to caller
*
* -------------------------------------------------------------------
* DEFINE STORAGE FOR DERIVED FIELDS
*
OFFSET DS F relative address of the converted word
*
* -------------------------------------------------------------------
* DEFINE INPUT RECORD(S)
* -------------------------------------------------------------------
*
* DEFINE TABLE FWRDS
*
FWRDS DC 0F
DC X'00FF00FF'
DC X'ABCDEF01'
DC X'FFFFFFFF'
DC X'00000000'
DC X'AAAAAAAA'
DC X'33333333'
DC X'12345678'
DC X'FFFFFFFF'
WORDCNT EQU (*-FWRDS)/(L'FWRDS) NUMBER OF WORD ELEMENTS
* -------------------------------------------------------------------
* DEFINE OUTPUT RECORD(S)
* -------------------------------------------------------------------
*
* DEFINE HEADER RECORD(S)
*
COL0SIZE EQU L'HEXADDR SIZE OF COLUMN 0 in all output records
COL1SIZE EQU L'HEXOUT SIZE OF COLUMN 1 in all output records
COL2SIZE EQU L'BINOUT SIZE OF COLUMN 2 in all output records
*
HEADER1 DC CL132' ' FULL HEADER INITIALLY BLANK
ORG HEADER1+COL0POS ALIGN AT COL0
DC C'OFFSET' OVERRIDE COLUMN0 NAME
ORG HEADER1+COL1POS ALIGN AT COL1
DC C'HEX VALUE' OVERRIDE COLUMN1 NAME
ORG HEADER1+COL2POS ALIGN AT COL2
DC C'BINARY VALUE' OVERRIDE COLUMN2 NAME
ORG , THE END OF HEADER1 LINE
*
HEADER2 DC CL132' ' FULL SUBHEADER INITIALLY BLANK
ORG HEADER2+COL0POS ALIGN AT COL0
DC (COL0SIZE)C'-' underscore COLUMN0 NAME
ORG HEADER2+COL1POS ALIGN AT COL1
DC (COL1SIZE)C'-' underscore COLUMN1 NAME
ORG HEADER2+COL2POS ALIGN AT COL2
DC (COL2SIZE)C'-' underscore COLUMN2 NAME
ORG , THE END OF HEADER2 LINE
*
* -------------------------------------------------------------------
* DEFINE OUTPUT DATA LINE
*
OUTREC1 DC CL132' ' FULL OUTPUT LINE, INITIALLY BLANKS
ORG OUTREC1 OVERLAY BY SUBFIELDS
DC CL1' ' INITIAL SPACE GAP
COL0POS EQU (*-OUTREC1)
HEXADDR DC CL8' ' OFFSET VALUE IN HEX
DC CL2' ' SPACE GAP AFTER OFFSET
COL1POS EQU (*-OUTREC1)
HEXOUT DC CL8' ' VALUE DISPLAYED IN HEX
DC CL2' ' SPACE GAP AFTER HEX VALUE
COL2POS EQU (*-OUTREC1)
BINOUT DC CL32' ' VALUE DISPLAYED IN BINARY
ORG , THE END OF OUTPUT LINE
*
********************** DATA AREAS *********************************
SAVEAREA DC 18F'0' AREA FOR MY CALLEE TO SAVE & RESTORE MY REGS
*
********************** DATA AREAS *********************************
FILEOUT DCB DSORG=PS, X
MACRF=(PM), X
DEVD=DA, X
DDNAME=FILEOUT, X
RECFM=FB, X
LRECL=132 MUST CORRESPOND TO THE REAL OUTPUT LINE
* -------------------------------------------------------------------
* define the translation table to convert
* bytes X'F0'-X'FF' to characters C'0'-C'F'
HEXTRAN EQU *-X'F0' set virtual start of translation table
DC C'0123456789ABCDEF' real part of translation table
* -------------------------------------------------------------------
LTORG ,
YREGS
END
The same can be done shorter, and using only original set of S/360 instructions.
Also the way of usage the constants, comments, and other entities doesn't help understanding the logic of code, especially for beginners.
Code:
*====================================================================
* Hex unpack of up to 65535 input bytes into 131070 output characters
*====================================================================
* Input parameters
* R0 - input length <= 65535 (XL4'0000FFFF') X'0000LLLL'
* R14 - input address
* R15 - output address
*
* R1 - is used as work register
*
* START OF THE CONVERSION LOOP
NEXTBYTE DS 0H START LOOP ON INPUT BYTES
SLL R0,12 X'0LLLL000' PREPARE SPACE AT THE END OF R0
*
IC R0,0(R14) X'0LLLL0ab' COMBINE BOTH LENGTH, AND INPUT BYTE
SRDL R0,4 X'00LLLL0a',X'b???????'
SLL R0,4 X'0LLLL0a0',X'b???????'
SLDL R0,4 X'LLLL0a0b',X'???????0'
STH R0,0(R15) X'0a0b' TWO NIMBLES NOW STORED IN TWO BYTES
* Now the two new output bytes are filled with codes X'00'-X'0F'
* All of them need to be replaced with C'0'-C'F'
TR 0(2,R15),=C'0123456789ABCDEF' translate two bytes at once
*
LA R14,1(R14) SKIP TO NEXT INPUT BYTE
LA R15,2(R15) SKIP TO NEXT OUTPUT BYTE
SRL R0,16 X'0000LLLL' SAVE LENGTH TO INITIAL POSITION
BCT R0,NEXTBYTE REPEAT LOOP ON BYTES; UPDATE THE COUNTER
* END OF THE CONVERSION LOOP
The code can be simplified when free to use extra registers (when not inside a macro)
And now to convert a string to readable bit string, optionally with a delimiter between each byte expansion..
Code:
*-
* r14 source addr
* r15 source length
* r0 work
* r1 target addr
* r2 source byte
* r3 # bits in a byte
*-
laey r14,hexstr
laey r15,l'hexstr
laey r1,bitstr
j b
a cli dlm,0 delimiter?
je b
mvc 0(1,r1),dlm add delimiter
la r1,1(,r1) bump target addr
b icm r2,b'1000',0(r14) insert byte at top
la r3,8 # of bits in a byte
c lr r0,r2 copy to work
srl r0,31 move bit to low pos
ahi r0,x'f0' make into ebcdic
stc r0,0(r1) save
la r1,1(,r1) bump target
rll r2,r2,1 rotate to position next bit
bct r3,c repeat if any bits left
la r14,1(,r14) bump source
bct r15,a repeat if any bytes left
j d
dlm dc c'.' delimiter
hexstr dc x'12C125'
bitstr dc cl(4*8)' ' 00010010.11000001.00100101
d ds 0h
Don't know when LAEY came around. The PoP has 2 Load Address Extended instruction -
The displacement for LAE is treated as a 12-bit unsigned binary integer. The displacement for LAEY is treated as a 20-bit signed binary integer.
Don't know when LAEY came around. The PoP has 2 Load Address Extended instruction -
The displacement for LAE is treated as a 12-bit unsigned binary integer. The displacement for LAEY is treated as a 20-bit signed binary integer.
Yes, those two come with Extended Addressability option.
For some reason they are not mentioned in the detailed IBM guide of 2016…