¿ªÔÆÌåÓý

ctrl + shift + ? for shortcuts
© 2025 Groups.io

Hex dump.


 

Probably an OT question, if this is the case, apologies.

I've a curiosity about the faster way to code, in IFOX00
assembler, hexadecimal stream dump, for an arbitrary long
string of bytes, possibly with a length not a multiple
of a full 32 bit word.

The best way I've seen so for, for a full 32 bit word, is
this sequence of instructions:

...
UNPK DB(9),FW(5)
TR DB(8),TRHEXTAB
...
DB DS D
DB2 DS D
FW DS F HEXTAB DC C'0123456789ABCDEF'
TRHEXTAB EQU HEXTAB-C'0'

which dump a full 32 bit word in 4 hexadecimal digits, assuming
the word is stored at the FW address, basically using 2 instructions.

If the stream length is not a multiple of 4, the remain, which length
is in the {1,2,3} set, may be dumped using the same sequence, slightly
modified, for example for 3:

UNPK DB(7),FW(4)
TR DB(6),TRHEXTAB

Any faster way?

Peppe.


 

Peppe,

For me today's PCs are so fast (and I'm the only user) that the speed
of an individual routine seldom matters.

Below is my code to expand any length of binary data into character
hexadecimal format.

Wally

...
LM RE,RF,ISPVAR R14 @ VARIABLE, R15 HAS LENGTH

LA R5,ISPOUT R5 @ WTP CHARACTER OUTPUT

ISP00100 LA R6,2 R6 # HEX CHARACTERS IN A BYTE

SR R1,R1 R1 WILL HAVE BYTE BEING PROCESSED

ICM R1,8,0(RF) R1 HAS 2 HEX VALUES IN UPPER BYTE

ISP00200 SR R0,R0 R0 WILL HAVE HEX BEING PROCESSED

SLDL R0,4 R0 HAS SINGLE HEX CHARACTER

STC R0,0(R0,R5) SAVE HEX IN OUTPUT AREA

TR 0(1,R5),ISPTRT1 TRANSLATE X'00-0F' TO X'F0-C6'

LA R5,1(R0,R5) R5 @ WTP NEXT BIT CHARACTER

BCT R6,ISP00200 LOOP - PROCESSING 1 BYTE

LA RE,1(R0,RE) R14 @ NEXT BYTE OF VALUE

BCT RF,ISP00100 LOOP - PROCESSING ALL BYTES
...
ISPTRT1 DC X'0123456789ABCDEF' USED TO CONVERT HEX CHARACTERS
...
ISPVAR DS A @ INPUT BINARY VARIABLE FIELD

ISPVARL DS A LENGTH OF VARIABLE
ISPOUT DS A @ OUTPUT CHARACTER FIELD

-----Original Message-----
From: [email protected] <[email protected]> On Behalf Of Giuseppe
Vitillaro
Sent: Monday, July 27, 2020 04:00 AM
To: [email protected]
Subject: [H390-MVS] Hex dump.

Probably an OT question, if this is the case, apologies.

I've a curiosity about the faster way to code, in IFOX00 assembler,
hexadecimal stream dump, for an arbitrary long string of bytes,
possibly with a length not a multiple of a full 32 bit word.

The best way I've seen so for, for a full 32 bit word, is this
sequence of instructions:

...
UNPK DB(9),FW(5)
TR DB(8),TRHEXTAB
...
DB DS D
DB2 DS D
FW DS F
HEXTAB DC C'0123456789ABCDEF'
TRHEXTAB EQU HEXTAB-C'0'

which dump a full 32 bit word in 4 hexadecimal digits, assuming the
word is stored at the FW address, basically using 2 instructions.

If the stream length is not a multiple of 4, the remain, which length
is in the {1,2,3} set, may be dumped using the same sequence, slightly
modified, for example for 3:

UNPK DB(7),FW(4)
TR DB(6),TRHEXTAB

Any faster way?

Peppe.






--
This email has been checked for viruses by AVG.


 

On Mon, 27 Jul 2020, Wally Mclaughlin wrote:

Peppe,

For me today's PCs are so fast (and I'm the only user) that the speed
of an individual routine seldom matters.

Below is my code to expand any length of binary data into character
hexadecimal format.

Wally

...
LM RE,RF,ISPVAR R14 @ VARIABLE, R15 HAS LENGTH

LA R5,ISPOUT R5 @ WTP CHARACTER OUTPUT

ISP00100 LA R6,2 R6 # HEX CHARACTERS IN A BYTE

SR R1,R1 R1 WILL HAVE BYTE BEING PROCESSED

ICM R1,8,0(RF) R1 HAS 2 HEX VALUES IN UPPER BYTE

ISP00200 SR R0,R0 R0 WILL HAVE HEX BEING PROCESSED

SLDL R0,4 R0 HAS SINGLE HEX CHARACTER

STC R0,0(R0,R5) SAVE HEX IN OUTPUT AREA

TR 0(1,R5),ISPTRT1 TRANSLATE X'00-0F' TO X'F0-C6'

LA R5,1(R0,R5) R5 @ WTP NEXT BIT CHARACTER

BCT R6,ISP00200 LOOP - PROCESSING 1 BYTE

LA RE,1(R0,RE) R14 @ NEXT BYTE OF VALUE

BCT RF,ISP00100 LOOP - PROCESSING ALL BYTES
...
ISPTRT1 DC X'0123456789ABCDEF' USED TO CONVERT HEX CHARACTERS
...
ISPVAR DS A @ INPUT BINARY VARIABLE FIELD

ISPVARL DS A LENGTH OF VARIABLE
ISPOUT DS A @ OUTPUT CHARACTER FIELD
Yep, that the other way I know about, going nibble
by nibble, hex digit to hex digit, using ICM/TR for
each nibble, along the byte stream.

I bet it is slower, although I didn't benchmark
them, compared to UNPK/TR which dump 4 hex digits
with one UNPK instruction.

Modern PC are fast, a PI3 is not so fast, it looks,
from hercules emulation point of view, not far from
mainframes of the eighty, 10MIPS against 200MIPS of
a XEON/I7.

From the other side, speaking of emulation, I guess
emulating UNPK is not as fast as an ICM. On a real
iron mainframe probably the game is different.

Other ways?

Peppe.


 

Well, do it as two passes.
Use the maximum length of the UNPK instruction then the left over part.
Then do the translate which has a 256 byte limit.

On Mon, Jul 27, 2020 at 2:59 AM Giuseppe Vitillaro
<giuseppe@...> wrote:

Probably an OT question, if this is the case, apologies.

I've a curiosity about the faster way to code, in IFOX00
assembler, hexadecimal stream dump, for an arbitrary long
string of bytes, possibly with a length not a multiple
of a full 32 bit word.

The best way I've seen so for, for a full 32 bit word, is
this sequence of instructions:

...
UNPK DB(9),FW(5)
TR DB(8),TRHEXTAB
...
DB DS D
DB2 DS D
FW DS F
HEXTAB DC C'0123456789ABCDEF'
TRHEXTAB EQU HEXTAB-C'0'

which dump a full 32 bit word in 4 hexadecimal digits, assuming
the word is stored at the FW address, basically using 2 instructions.

If the stream length is not a multiple of 4, the remain, which length
is in the {1,2,3} set, may be dumped using the same sequence, slightly
modified, for example for 3:

UNPK DB(7),FW(4)
TR DB(6),TRHEXTAB

Any faster way?

Peppe.





--
Mike A Schwab, Springfield IL USA
Where do Forest Rangers go to get away from it all?


 
Edited

Giuseppe Vitillaro wrote:

Probably an OT question, if this is the case, apologies.
Actually, a forum DOES exist for exactly such questions. It's called "hercules-s370asm" (Forum discussing use of S/370 assembler with the Hercules emulator):


/g/hercules-s370asm


(Ref: )

But given how infrequently Off Topic posts are made here and to other forums (and the fact that such topics of discussion are usually quite short lived and don't drag on for days and weeks on end), I personally am of the opinion that in this specific instance such an off topic post here should be okay. :)

p.s. Doesn't a system function or macro already exist to do this? It seems like such a common thing! If such a macro doesn't already exist maybe someone could write one?

--
"Fish" (David B. Trout)
Software Development Laboratories

mail: fish@...


 

On Mon, 27 Jul 2020, Mike Schwab wrote:

Well, do it as two passes.
Use the maximum length of the UNPK instruction then the left over part.
Then do the translate which has a 256 byte limit.
Yep, I had some thought about this way, which actually seems
the faster way to go for "long streams" (which it is actually my case
as I'm coding a PL/I-F small program to hex dump datasets, please
I know IDCAMS may do the job under MVS3.8j, but it is a PL/I exercise from one side and I like to get UNIX like HEX/EBCDIC dump, identical
to the output of "xxd -E" under UNIX).

But in this case the remainder should have a variable size between
1 and 125 (maximum should be 126 bytes, 252 hex digits, executing a single UNPK/TR couple).

So, it can't be coded using one routine for each value of the remainder,
too long and a nightmare to modify, but it requires, I guess, to write
the UNPK/TR instructions LL fields, at runtime, executing them only
after their LL fields are correctly defined for current value
of the remainder.

Which directly lead to the "EX" instruction, if I got the correct
picture, an "EX" for UNPK and an "EX" for TR.

Am I on the right side of the "force"? ;-) Or there are better ways?

Peppe.


 

Hi Peppe,

The maximum length of a UNPK is 8 (length 1 = 8 and length 2 = 15).
UNPK is SS-2 type instruction with 2 length fields rather than a SS-1 type instruction
with a length field with a maximum of 255.
So you can convert max 7 bytes in one time to "printable" HEX.
An example is the SYCONVHX macro in the RPF source library.

Cheers,
Rob


 

Yes, EX is used to put varying lengths into instructions.
And if you are doing 4 or 8 groups of 8 nibbles and a blank into a
print line of 80 or 132,
do the unpacks then translate the bytes then move the blanks.

On Tue, Jul 28, 2020 at 4:00 AM Giuseppe Vitillaro
<giuseppe@...> wrote:

On Mon, 27 Jul 2020, Mike Schwab wrote:

Well, do it as two passes.
Use the maximum length of the UNPK instruction then the left over part.
Then do the translate which has a 256 byte limit.
Yep, I had some thought about this way, which actually seems
the faster way to go for "long streams" (which it is actually my case
as I'm coding a PL/I-F small program to hex dump datasets, please
I know IDCAMS may do the job under MVS3.8j, but it is a PL/I exercise
from one side and I like to get UNIX like HEX/EBCDIC dump, identical
to the output of "xxd -E" under UNIX).

But in this case the remainder should have a variable size between
1 and 125 (maximum should be 126 bytes, 252 hex digits, executing
a single UNPK/TR couple).

So, it can't be coded using one routine for each value of the remainder,
too long and a nightmare to modify, but it requires, I guess, to write
the UNPK/TR instructions LL fields, at runtime, executing them only
after their LL fields are correctly defined for current value
of the remainder.

Which directly lead to the "EX" instruction, if I got the correct
picture, an "EX" for UNPK and an "EX" for TR.

Am I on the right side of the "force"? ;-) Or there are better ways?

Peppe.



--
Mike A Schwab, Springfield IL USA
Where do Forest Rangers go to get away from it all?


 

On Tue, 28 Jul 2020, Rob Prins via groups.io wrote:

Hi Peppe,
The maximum length of a UNPK is 8 (length 1 = 8 and length 2 = 15).
UNPK is SS-2 type instruction with 2 length fields rather than a SS-1 type instruction
with a length field with a maximum of 255.
So you can convert max 7 bytes in one time to "printable" HEX.
An example is the SYCONVHX macro in the RPF source library.
Cheers,
Rob _._,_._,_

Ouch, I missed this, thanks Rob!

So it is actually easier, maximum 7 bytes,
i.e. 14 hex digits.

In any case probably the "EX" instruction is
the easier way to go?

Shouldn't coding unrolled 7 routines for each
remainder faster?

Peppe.


 

On Tue, 28 Jul 2020, Mike Schwab wrote:

Yes, EX is used to put varying lengths into instructions.
And if you are doing 4 or 8 groups of 8 nibbles and a blank into a
print line of 80 or 132,
do the unpacks then translate the bytes then move the blanks.
Yep, I think I'm converging ;-)

TR/MVC instructions have an LL field which may handle
up to 256 bytes, while UNPK use the LL field for both
source and target, up to 7 digits.

Which lead to a loop for UNPK, modulo 7, up to a complete
256 bytes buffer ready for "TR/MVC", modulo 256.

This should be the faster way, probably.

Lol ... more I understand of 370 arch more fun I get ;-)

Peppe.


 

Hi Peppe,

An EX instruction is OR'ing the low order 8 bits of the R1 (mentioned in the EX instruction)
over bits 8-15 of the instruction that is OR'ed. So be careful to EX to a SS-2 type instruction.

The length fields of a SS-2 type instruction does have a maximum of 16.? In the object code of
the instruction the length is always minus 1.
So, the If you want to pack 16 bytes the low order 8 bits of the register in the EX should contain
e.g. 7F (PACK? field1(8),field2(16))

Cheers,
Rob


 

On Tue, 28 Jul 2020, Rob Prins via groups.io wrote:

Hi Peppe,
An EX instruction is OR'ing the low order 8 bits of the R1 (mentioned in the EX
instruction)
over bits 8-15 of the instruction that is OR'ed. So be careful to EX to a SS-2 type
instruction.
The length fields of a SS-2 type instruction does have a maximum of 16. In the object
code of
the instruction the length is always minus 1.
So, the If you want to pack 16 bytes the low order 8 bits of the register in the EX
should contain
e.g. 7F (PACK field1(8),field2(16))

Thanks Rob, your advices are appreciated.

Currently, as an example, I'm looking to a PL/I
(for the modern Z/OS PL/I compiler) assembler
routine DWNSHEX (got it from CBT, I don't remember
the name of the original package):

* THIS SUBROUTINE SHOULD BE DECLARED AS FOLLOWS :-
* DCL DWNSHEX ENTRY(BIT(*) ALIGNED) RETURNS(CHAR(???) VAR);
* WHERE ??? SHOULD BE REPLACED BY ANY NUMBER SUITABLY LARGE FOR THE
* PARTICULAR APPLICATION PROGRAM.
* TO CALL THIS SUBROUTINE (ACTUALLY A FUNCTION) ONE SHOULD CODE
* SOMETHING LIKE :-
* HEX_CHARS = DWNSHEX(BIT_STRING);
* OR
* HEX_CHARS = DWNSHEX(UNSPEC(ANY_VARIABLE));
*
* AUTHOR :- DAVID W NOON
* APRIL 1990

to hex dump a BIT string.

It doesn't look so different from what I'm trying to
achieve, it actually use EX for TR/MVC, although
in a different way, to solve a different problem
(HEX function is a builtin function in modern PL/I
implementations).

In the line of principle it can even adapted to PL/I-F,
changing the calling sequence, but I bet dumping
a BIT PL/I variable (using UNSPEC on a string)
would be slower than directly dumping a string.

Peppe.


 

Hi Peppe,

Below you will find an example for a HEXCONV.
This piece of code is used in the RPF browser for load modules.

HEXCONV? DS??? 0H?????????????????????????????????????????????????????
???????? ST??? R14,SAVE14HX??????????? Save register 14???????????????
???????? LR??? R6,R1?????????????????? Save length????????????????????
???????? MVI?? RECHEX1,X'40'?????????? Blank the??????????????????????
???????? MVC?? RECHEX1+1(L'RECHEX1-1),RECHEX1?? records???????????????
???????? MVC?? RECHEX2,RECHEX1???????????????????????? first??????????
???????? LA??? R3,RECORD+10??????????? Point to record with data??????
???????? LA??? R4,RECHEX1+10?????????? Point to record with hi nibbles
???????? LA??? R5,RECHEX2+10?????????? Point to record with lo nibbles
HEXC005? DS??? 0H?????????????????????????????????????????????????????
???????? MVC?? RHEXINP,0(R3)?????????? Input character from record????
???????? SYCONVHX IN=RHEXINP,OUT=RHEXOUT,L=1 convert to printable hex?
???????? MVC?? 0(1,R4),RHEXOUT???????? Move 1st nibble in 1st record??
???????? MVC?? 0(1,R5),RHEXOUT+1?????? Move 2nd nibble in 2nd record??
???????? LA??? R3,1(,R3)?????????????? Next pos. input rec with chars?
???????? LA??? R4,1(,R4)?????????????? Next pos. record with hi nibbles
???????? LA??? R5,1(,R5)?????????????? Next pos. record with lo nibbles
???????? BCT?? R6,HEXC005????????????? Loop until all done????????????
???????? MVC?? RECORD,RECHEX1????????? Move record with high nibbles??
???????? PUT?? RPFPRT2,OUTAREA???????? Write record???????????????????
???????? MVC?? RECORD,RECHEX2????????? Move record with low? nibbles??
???????? PUT?? RPFPRT2,OUTAREA???????? Write record???????????????????
???????? L???? R14,SAVE14HX??????????? Restore register 14????????????
???????? BR??? R14

I start here at offset 10 (see the loadmodule browse of RPF 1.8.3).
Length is in register 1.

Cheers,
Rob
???????????????????????????????