Next we will create a macro to dump a block of memory. It will call our @PRINT macro to write the dump to the printer device. Like the @PRINT macro there are two forms GEN=YES and GEN=NO.
MACRO &NAME @DUMP &ADDR,&LEN,&GEN=NO LCLC &NDX &NDX SETC '&SYSNDX' AIF ('&GEN' EQ 'YES').GEN &NAME @RGCK &ADDR,REG=R1 @RGCK &LEN,REG=R0 LA R15,@DUMP BALR R14,R15 MEXIT ,
We start just like the @PRINT macro and set up a variable for generating local labels. The beginning address of the storage to be dumped is placed into register 1 using the @RGCK macro and the length to dump is loaded into register 0. Our subroutine @DUMP is then called to format and print the storage.
.GEN ANOP , @DUMP STM R14,R12,12(R13) LA R15,@&NDX.80 NEW SAVE AREA ST R15,8(,R13) ST R13,4(,R15) LR R13,R15 * LR R10,R1 DATA ADDRESS LR R11,R0 LENGTH AR R11,R10 END ADDRESS * N R10,@&NDX.83 ALIGN
We start by saving the callers registers in the save area provided by the caller pointed to by register 13. We then chain on our save area and copy the data address into register 10 and the length into register 11. If the beginning address does not begin on an even boundary we back it up using an AND with a mask of X’00FFFFF0′.
@&NDX.01 DS 0H MVI @&NDX.70,C' ' CLEAR PRINT BUFFER MVC @&NDX.70+1(L'@&NDX.70-1),@&NDX.70 ST R10,@&NDX.81 ADDRESS UNPK @&NDX.82(9),@&NDX.81(5) TR @&NDX.82(8),@&NDX.99-C'0' MVC @&NDX.71,@&NDX.82 * MVC @&NDX.74,0(R10) TR @&NDX.74,@&NDX.98 KEEP ONLY PRINTABLE
Now we start the main outer loop by clearing out our print buffer. Next we save the address into a full word work area. Using the UNPK instruction and a TR we convert it to printable characters. The UNPK will convert each byte into two bytes with the value X’F0′ to X’FF’. Our translation table contains ‘0123456789ABCDEF’. By using the address of our translate table and subtracting our offset of X’F0′ (C’0′) we have translated a hex address to a printable string.
We then copy the target data are to our print buffer and using a second translate table we convert any unprintable characters to a period (x’4B’).
* LA R2,@&NDX.72 FIRST DATA AREA LA R3,4 @&NDX.02 DS 0H MVC @&NDX.81(4),0(R10) UNPK @&NDX.82(9),@&NDX.81(5) TR @&NDX.82(8),@&NDX.99-C'0' MVC 0(8,R2),@&NDX.82 LA R10,4(,R10) LA R2,9(,R2) BCT R3,@&NDX.02 *
Now we set up for the inner loop to translate the 16 bytes of data into printable strings. We set up the loop with register 2 pointing into the print buffer and register 3 with a value of 4 (4 groups of 4 bytes).
Using the same sequence of UNKP and TR we translate the data contents into hex data strings. We then increment the source and target pointers and use BCT to loop back if still more data to process for the line.
* @PRINT @&NDX.70 * * CR R10,R11 STILL MORE TO DO BL @&NDX.01 YES - LOOP BACK * * L R13,4(,R13) LM R14,R12,12(R13) BR R14 *
Now we use our @PRINT macro to print the formatted line. Next we check to see if we have reached our end address. If not we loop back and print another line. When done we unchain the save area, restore registers and return to the caller.
* @&NDX.70 DC CL132' ' ORG @&NDX.70 @&NDX.71 DS CL8 DS CL2 @&NDX.72 DS CL8,CL1,CL8,CL1,CL8,CL1,CL8,CL2 @&NDX.74 DS CL16 ORG , * @&NDX.80 DC 18F'0' @&NDX.81 DC F'0' @&NDX.82 DC CL9'0' DS 0F @&NDX.83 DC X'00FFFFF0' *
All that is left is to define our data area. First is our print buffer which is 132 bytes long. Using ORG we overlay it with our data fields for the storage address, the hex representation of the data and the character representation.
We then define our save area, our work area for the UNPK processing and our beginning address mask.
Finally we define our two translate tables (see full listing).
Full macro listing below:
MACRO &NAME @DUMP &ADDR,&LEN,&GEN=NO LCLC &NDX &NDX SETC '&SYSNDX' AIF ('&GEN' EQ 'YES').GEN &NAME @RGCK &ADDR,REG=R1 @RGCK &LEN,REG=R0 LA R15,@DUMP BALR R14,R15 MEXIT , .* .* .GEN ANOP , @DUMP STM R14,R12,12(R13) LA R15,@&NDX.80 NEW SAVE AREA ST R15,8(,R13) ST R13,4(,R15) LR R13,R15 * LR R10,R1 DATA ADDRESS LR R11,R0 LENGTH AR R11,R10 END ADDRESS * N R10,@&NDX.83 ALIGN @&NDX.01 DS 0H MVI @&NDX.70,C' ' CLEAR PRINT BUFFER MVC @&NDX.70+1(L'@&NDX.70-1),@&NDX.70 ST R10,@&NDX.81 ADDRESS UNPK @&NDX.82(9),@&NDX.81(5) TR @&NDX.82(8),@&NDX.99-C'0' MVC @&NDX.71,@&NDX.82 * MVC @&NDX.74,0(R10) TR @&NDX.74,@&NDX.98 KEEP ONLY PRINTABLE * LA R2,@&NDX.72 FIRST DATA AREA LA R3,4 @&NDX.02 DS 0H MVC @&NDX.81(4),0(R10) UNPK @&NDX.82(9),@&NDX.81(5) TR @&NDX.82(8),@&NDX.99-C'0' MVC 0(8,R2),@&NDX.82 LA R10,4(,R10) LA R2,9(,R2) BCT R3,@&NDX.02 * * @PRINT @&NDX.70 * * CR R10,R11 STILL MORE TO DO BL @&NDX.01 YES - LOOP BACK * * L R13,4(,R13) LM R14,R12,12(R13) BR R14 * * @&NDX.70 DC CL132' ' ORG @&NDX.70 @&NDX.71 DS CL8 DS CL2 @&NDX.72 DS CL8,CL1,CL8,CL1,CL8,CL1,CL8,CL2 @&NDX.74 DS CL16 ORG , * @&NDX.80 DC 18F'0' @&NDX.81 DC F'0' @&NDX.82 DC CL9'0' DS 0F @&NDX.83 DC X'00FFFFF0' * * @&NDX.98 DS 0C * 0 1 2 3 4 5 6 7 8 9 A B C D E F DC X'4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B' 00 DC X'4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B' 10 DC X'4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B' 20 DC X'4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B' 30 DC X'4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B' 40 DC X'504B4B4B4B4B4B4B4B4B5A5B5C5D5E5F' 50 DC X'60614B4B4B4B4B4B4B4B6A6B6C6D6E6F' 60 DC X'4B4B4B4B4B4B4B4B4B4B7A7B7C7D7E7F' 70 DC X'4BC1C2C3C4C5C6C7C8C94B4B4B4B4B4B' 80 DC X'4BD1D2D3D4D5D6D7D8D94B4B4B4B4B4B' 90 DC X'4B4BE2E3E4E5E6E7E8E94B4B4B4B4B4B' A0 DC X'4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B' B0 DC X'4BC1C2C3C4C5C6C7C8C94B4B4B4B4B4B' C0 DC X'4BD1D2D3D4D5D6D7D8D94B4B4B4B4B4B' D0 DC X'4B4BE2E3E4E5E6E7E8E94B4B4B4B4B4B' E0 DC X'F0F1F2F3F4F5F6F7F8F94B4B4B4B4B4B' F0 * * @&NDX.99 DC C'0123456789ABCDEF' MEND ,