How to Print a Register

A friend of mine, Melvyn Maltz, was amused by some code I wrote recently. The code simply printed out the contents of a register, and I took a quick and dirty approach:  Store the register in a buffer, use PUT to print the buffer, SET HEX ON.  It’s a technique I often use when debugging on a mainframe.  I should tell you that my friend is an expert in most things IBM – a master programmer. He’s also generous enough to read or watch some of the material on this site and offer suggestions. In any case, the code amused him, and he reminded me that it’s not that hard to print a register – and it’s instructive.  I realized I had never written about how to print a hexadecimal representation of a register (or small field) on this site, so I’ll do that now.  It involves TR and UNPK.

Let’s start with UNPK which treats each byte of the sending field (except the last) the same. UNPK separates the zone and numeric parts of each byte (dare I call them nibbles?) into two bytes after appending a hexadecimal F on the front of each nibble, like this:

   | B 3 |
     /  \
| F B| F 3 |

A moment’s thought here is instructive.  The 3 is converted to x’F3’, which is exactly what we need to print it in a character format.  The same would be true for all digits 0-9. The treatment given to B doesn’t work so well.  The same bad treatment would occur for digits A-F. So, bytes x’FA’, x’FB’, … x’FF’ would have to be repaired after applying UNPK.  Can we fix those?  Yes.  TR can do the trick.  

So, the basic idea is to use UNPK followed by TR.  What about that last byte that UNPK converts by simply flipping the nibbles?  We can avoid that problem by adding a byte (logically or physically) to the field we are unpacking. Problem solved.

What about the TR table?  What does that look like?  My friend might suggest this,

HEXTABLE    DC    C’0123456789ABCDEF’

How do we get away without defining a 256-byte table? The solution leverages the fact that we are only translating a narrow range of sequential values:  x’F0’ – x’FF’  – every byte we need to translate begins with x’F’.  We can pretend to have created a 256-byte table by coding TR this way (assuming the register we want to print is R5):

            ST   R5,FWRD
            UNPK HEXAREAX,FWRDX
            TR   HEXAREA,HEXTABLE-240
            …
            DS  0F           ALIGNMENT
  FWRDX     DS  0CL5
  FWRD      DS   F
            DC   X'00'       AN EXTRA BYTE FOR UNPK
  HEXAREAX  DS  0CL9         8 HEX DIGITS+1 IN CHARACTER
  HEXAREA   DS   CL8         8 HEX DIGITS IN CHARACTER 
            DC   X'00'       AN EXTRA BYTE FOR UNPK

We can do this, confident that the first 240 bytes of our fictitious table will never be referenced by TR. (240 is the offset to a character 0). After translation, HEXAREA contains the result. Variations of this technique use explicit lengths and leaving off an extra byte. The only drawback to the technique is that the relative address HEXTABLE-240 may generate an addressability error if it references an address that is smaller than the base register address. This rarely happens.

My friend may get another chuckle out of this, but I’m going to suggest a second solution that uses a 256-byte table:

HEXTABLE  DC   256AL1(*-HEXTABLE)   NEUTRAL TABLE          
          ORG  HEXTABLE+X'FA'       FIX X'FA' THROUGH X'FF'
          DC   C'ABCDEF'                                   
          ORG  ,      

The rest of the solution is similar and looks like this:       

          ST    R5,FWRD
          UNPK  HEXAREAX,FWRDX   UNPK SLIGHTLY LARGER FIELDS
          TR    HEXAREA,HEXTABLE TRANSLATE THE SMALLER FIELD
          …
          DS  0F           ALIGNMENT
FWRDX     DS  0CL5
FWRD      DS   F
          DC   X'00'       AN EXTRA BYTE FOR UNPK
HEXAREAX  DS  0CL9         8 HEX DIGITS+1 IN CHARACTER FORMAT
HEXAREA   DS   CL8         8 HEX DIGITS IN CHARACTER FORMAT
          DC   X'00'       AN EXTRA BYTE FOR UNPK

After executing the first three lines above, HEXAREA will contain a printable version of register 5.

This leads into how we can print larger areas of memory in a hexadecimal format. There’s always the old standby:  SNAP.  Melvyn sent a nice example of TROT, but I’ll save that gem for another post.

Leave a comment

Filed under IBM Mainframe Assembler

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.