Anne The contents of the register, given the symbolic name R0 in this example, are stored in the double-word, eight bytes that used to need to be double-word aligned but probably don't any more, a storage area identified by RWORK in this case. The contents are stored in packed decimal format. This means that the result is the number expressed as decimal digits, one digit occupying half a byte. The digits are stored from the second half-byte from the right end of the field half a byte at a time moving leftwards. The rightmost half-byte contains either X'C' in the number is positive or X'D' if the number is negative.[1]
The edit mask X'402120202020', specified using a "literal", is moved to a field identified as a location one byte less than the field identified by the name M1CC. What we can't see is how the length L'M1CC, the number the Assembler notes as the length depending on how the field M1CC was defined, plus one matches up to the length 6 which is the length of the literal. It seems reasonable that the field M1CC is defined as having length 5. If not, the programming is a mess. If so, the "L'M1CC+1" specification is stupid. It's stupid because the expression already indicates the length by virtue of having included the literal which - dare I say literally - no, I'll just say - obviously has length 6. I'll proceed on the assumption that M1CC is a field of length 5. The contents of the area defined by the location RWORK+5, 5 bytes into the double-word area are now taken a half-byte at a time and managed according to the "edit mask". If the edit mask specifies X'20" or X'21', a half-byte containing what should be a decimal number, i.e. a number from 0 to 9 (and *not* X'A' to X'F'), replaces the X'20' or X'21' character simply by taking the half-byte and prepending a X'F' before storing over the X'20' or X'21' byte. If the character is other than X'20' or X'21', there is, in principle, no change[2]. The first character is important in that it can be used also as a substitute for "0", X'F0', if there have been no previous non-zero half-bytes selected. Clearly a "blank", X'40', means that "leading zeros" are suppressed with blank characters, Another popular alternative is an "asterisk", "*", X'5C', which can be used when printing cheques ("chiefly Amer." check). Why X'20' and X'21'? X'21' has an additional function which switches off the suppressing "leading zeros" mechanism. [2] The "in principle" is because the character can be replaced by the first byte if "leading zeros" are still being suppressed. Think of how "commas" separating groups of 3 decimal digits would need to show up. Note that the "edit mask" specifies 5 bytes containing X'20" or X'21'. This means that 5 half-byte decimal values will be selected from storage area RWORK+5 and this happens to be all the packed decimal half-bytes up to the last half-byte, the "sign half-byte". All very neat. Note also that this pattern of coding works well for an odd number of eventual decimal digits since the result can usually be "unwrapped" into the target location needing only a single initial typically blank character. For an even number of characters, the "unwrapping can be performed into the target location if two leading blanks are available - or the field to the left can be moved in after the decimal digits are "unwrapped" rather than before - or the "unwrapping" can be performed in a work area and the data without the necessary prefix moved to the target location. Incidentally, using this coding, the programmer had better be sure that he/she doesn't care about the byte immediately in front of the M1CC field since it gets trashed by the first byte of the literal. It's not really good coding practice, this "minus" addressing. What this means in your case is that the 5 lower digits of the binary number stored in the register will show as a string of digits with no "leading zeros" suppressed. Once all this has been done it's far too late to consider presenting the binary number in the register as a hexadecimal string; you need to start again - or, in a more American version of the language - to start over. <g> As the reputed Irishman said, "If oi wanted to go there, oi wouldn't start from here!" <g> What you have done with your instructions achieves nothing since, after execution, the contents of field M1CC is unchanged. In effect your first instruction removers the first half-byte of all but the first byte of the assumed 5-byte M1CC field and then the second instruction simply puts the X'F' half-bytes back. Never code anything without understanding it. One reason it isn't translating decimal to hexadecimal is because you don't understand it. It's possible you didn't understand the context of the code you took as your sample. I know you have had at least one example of how the code you posted here works even if you didn't get the general description as above. Unfortunately, having given you sample code to achieve what you want, nobody has explained in detail what happens so you may be in the half-way house of having code which works while still not understanding it. In fact the "print hexadecimal" case is even trickier that the "print decimal" case since, in the letter case, all the instructions were doing precisely what the Principles of Operation says they do - even if the "edit" instruction is a bit complicated. There's a touch of "smoke and mirrors" about the various sample codings you have been offered for the former. Let's have a look at Shmuel's eventual offering, the following - with a missing bit of the "unpack" instruction inserted. This has the virtue of being as symbolic as possible. ST R0,BINWORK UNPK HEXWORK(L'HEXWORK+1),BINWORK(L'BINWORK+1) TR HEXWORK,TRTAB TRTAB EQU *-C'0' DC C'0123456789ABCDEF' BINWORK DS F HEXWORK DS CL8 DS C I don't think I need explain the "store register" instruction. Suffice to say that BINWORK now contains a full-word, 4 bytes, 8 half-bytes, binary number. The "unpack" instruction makes what is, in fact, an incorrect assumption. It, poor thing, *thinks* it is working on a packed decimal number - having the format I explained above. In fact the "unpack" instruction is being used in a clandestine way to "unwrap" the 8 half-bytes of the BINWORK field into the 8 bytes of the HEXWORK field, each in turn being taken a half-byte at a time, prepended with X'F' and stored a byte at a time. The reason for the extra "1" added to the length of both HEXWORK and BINWORK is that the "unpack" instruction, true to its defined role as an instruction for use with decimal fields, knows that it has to treat the last byte in the "from" field differently than the preceding bytes. That last byte simply has the two constituent half-bytes reversed before they are stored in the last byte of the "to" field. Because an additional byte was indicated in the "unpack" instruction the "last" byte is from outside the BINWORK field and, after the reversal, it is stored outside the HEXWORK field, The lengths in the "unpack" instruction are, in fact, 5 and 9 respectively rather than 4 and 8. Converting that "last" byte was actually a total waste of time and resources but it was forced on us because we lack the precise instruction for the task in hand and the "unpack" instruction, in essence, had to be fooled into doing the job for us. Whatever byte follows BINWORK is of no consequence since it is "read". Quite the contrary, whatever byte follows HEXWORK had better not matter since it is going to get "written" on. Just be sure this is taken care of either as a work area known to be used later or a wasted byte. What's tricky about the "translate" instruction is that you are obliged to pretend that it has a whole 256 bytes to work with so that each byte selected can be used to index into the table. What the "unpack" instruction did was to guarantee that the first half-byte of each character to be translated definitely contained X'F' and thus that the range of values to work on is from 240, X'F0', to 255, X'FF', rather than 0 to 255. Thus there is no harm in having the characters at positions 0 to 239 in the translate table consist of random code within the program leading up to the string of 16 characters we really need. Another sample from Alan Field is the following: ST R0,IN UNPK OUT(9),IN(5) MVZ OUT(8),OUT-1 TR OUT(8),=C'0123456789ABCDEF' This is the same as Shmuel's except that there is an additional instruction before the "translate" instruction and the "translate" is allowed to be a bit more honest. However, there is an assumption here which is that the byte at location OUT-1 needs to have the first half-byte, the "zone" half-byte, set to X'0'. Assuming this is the case, the "move zones" instruction will overwrite the "zone" half-byte in each of the 8 bytes in field OUT with X'0' replacing the X'F'. Now the "translate" instruction, still thinking it has a table of 256 bytes to work with, in fact only ever uses the first 16 bytes in the table for characters ranging from 0, X'00', to 15, X'0F'. Your original sample used the "and character" (NC) instruction in order to perform the same function as the "move zones" instruction in the example above. The "move zones" instruction is marginally more storage efficient - and I was brought up using Assembler programming in the days when storage efficiency was considered a virtue[1]: the "move zones" instruction needs just one additional byte whereas the "and character" instruction needs as many bytes as the field to be modified. So now I hope you not only have a piece of working code but even know *how* it works. <g> Incidentally Peter Hunkeler was right. Bill Fairchild, usually so reliable, must have has a minor rush of blood. <g> Chris Mason [1] In fact the "packed decimal standard", as it were, allows some flexibility in the hexadecimal digit which forms the, so-called, "sign half-byte". I forget every last detail but it may be as simple as only the lowest bit being significant and the rest ignored so that a positive number is one which has B'0' as this lowest bit and a negative number is one which has B'1' as this lowest bit - except that X'F' has to indicate a positive number - so maybe it's not quite so simple. Suffice to say that it was once proposed that the "Add Register" instruction code, X'1A', could be used as a positive packed decimal "1" when a package for some basic "spooling" in under 4K for DOS (now VSE) was being discussed (in the days before POWER obviously) and the author/presenter was canvassing for space-saving ideas. ----- Original Message ----- From: "Anne Crabtree" <[EMAIL PROTECTED]> Newsgroups: bit.listserv.ibm-main To: <IBM-MAIN@BAMA.UA.EDU> Sent: Tuesday, 24 October, 2006 9:11 PM Subject: Assembler question > Working on the IEFACTRT routine and it has the following assembler statements for getting return code ready to print on hasp: > > CVD R0,RWORK GET ADDRESS OF COND FIELD > MVC M1CC-1(L'M1CC+1),=X'402120202020' MOVE IN EDIT MASK > ED M1CC-1(L'M1CC+1),RWORK+5 CONVERT RET CODE TO CHAR > > However, I want the return code to print as hexidecimal instead of decimal. I tried the following after these prior 3 statements: > > NC M1CC+1(4),=4X'0F' > TR M1CC+1(4),=C'0123456789ABCDEF' > > (I don't understand exactly how this works but it is how it is coded in our old exit which used the SMF type 4 records). > > Why is it not translating the decimal to hexadecimal??? ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to [EMAIL PROTECTED] with the message: GET IBM-MAIN INFO Search the archives at http://bama.ua.edu/archives/ibm-main.html