Joined: 30 Nov 2013 Posts: 917 Location: The Universe
In a sense this is side post to what does this assembler code do. This post contains a couple of very strange uses of the TM instruction, so it might be a good idea to discuss the instruction in more detail.
In concept, a programmer uses TM to test one bit in a byte. For example TM DCBOFLGS, DCBOFOPN test a byte in a DCB to determine if the DCB is open, perhaps after an OPEN macro directed at the DCB. Programmers can specify several bits in the mask, and things get kind of strange after the TM executes. By the way, these are the condition code settings.
0 The target byte contains 0 bits for each 1 bit in the mask.
1 Some, but all bits in the target byte match a 1 bit in the mask
2--
3 All bits in the target byte specified by a 1 bit in the mask are 1
For example code like this is fairly common.
Code:
LA 14,DATA+L'DATA
BCTR 14,0
TM 0(14),255-C' '
BZ *-6
...
DATA DC CL8'text'
The 255-C' ' mask in the TM instruction is X'BF'. This is confusing, though at least the way the programmer specifies the mask gives the reader a clue as to its intention. Unfortunately, the *-6 address in the BZ instruction, violates another programming style rule; don't use * plus or minus something for two reasons: you can do the arithmetic wrong, and if there are several instructions in the range, and you insert or remove an instruction, then, by definition, the arithmetic becomes wrong. This *-6 becomes the address of the BCTR instruction: 4 bytes for the TM instruction and 2 bytes for the BCTR instruction.
Now let us suppose the data is C'text¬¬¬¬', where the ¬ symbol is standing in place for a real blank character. The LA instruction computes the address of the first byte after the data area and stores the address in register 14. The BCTR instruction subtracts 1 from the value in register 14 so it has the address of the last byte in the data area. The first time the TM instruction executes it finds a 0 bit for each 1 bit in the mask, so it sets condition code 0, and the BZ instruction branches to the BCTR instruction. The loop continues until it finds a non blank character. Think about why this is so.
Now what happens if the data area is all blank characters? Again, think about it. Finally, write code that will behave in a reliable way when the data area contains all blanks.
Formally, this example is correct as demonstration of the TM instruction functionality. But, as example of program logic implementation it is one of the worst approach, when a very simple task is solved by means of sophisticated tricks and gimmicks. Specifically:
- this way of checking for a space is strictly limited to EBCDIC code table, which is highly undesired.
- even in EBCDIC table, the legal characters '<', '(', '+', '|', and '¢' will be considered as "space-equivalent".
Plus, there is absolutely no benefits in using TM instruction instead of clear and simple CLI 0(14),C' ' instruction, isn't it?
Joined: 30 Nov 2013 Posts: 917 Location: The Universe
sergeyken wrote:
Formally, this example is correct as demonstration of the TM instruction functionality. But, as example of program logic implementation it is one of the worst approach, when a very simple task is solved by means of sophisticated tricks and gimmicks. Specifically:
- this way of checking for a space is strictly limited to EBCDIC code table, which is highly undesired.
- even in EBCDIC table, the legal characters '<', '(', '+', '|', and '¢' will be considered as "space-equivalent".
Plus, there is absolutely no benefits in using TM instruction instead of clear and simple CLI 0(14),C' ' instruction, isn't it?
- this way of checking for a space is strictly limited to EBCDIC code table, which is highly undesired.
True, but so what? ASCII is relatively rare in day to day work with common programs used on IBM mainframes, despite what ASCII proponents may think. CLI XXX,C' ' is just as EBCDIC dependent.
- even in EBCDIC table, the legal characters '<', '(', '+', '|', and '¢' will be considered as "space-equivalent".
Not one of those characters are considered as white space by any processing program I'm aware of.
- even in EBCDIC table, the legal characters '<', '(', '+', '|', and '¢' will be considered as "space-equivalent".
Not one of those characters are considered as white space by any processing program I'm aware of.
Vice versa:
I mean, when using the TM instruction, as in your example, then all the characters I mentioned will be considered as spaces! This is a serious logic fault caused by using a machine instruction for the purpose it is not supposed to be used.
When we need to check a character for blank value, the obvious way is, CLI 0(RX),C' ' instruction; under no circumstances test of specific bits of the character code by TM 0(RX),X'??' instruction should be used.
Joined: 30 Nov 2013 Posts: 917 Location: The Universe
sergeyken wrote:
steve-myers wrote:
- even in EBCDIC table, the legal characters '<', '(', '+', '|', and '¢' will be considered as "space-equivalent".
Not one of those characters are considered as white space by any processing program I'm aware of.
Vice versa:
I mean, when using the TM instruction, as in your example, then all the characters I mentioned will be considered as spaces! This is a serious logic fault caused by using a machine instruction for the purpose it is not supposed to be used.
When we need to check a character for blank value, the obvious way is, CLI 0(RX),C' ' instruction; under no circumstances test of specific bits of the character code by TM 0(RX),X'??' instruction should be used.
Code:
Loc Object Code Addr1 Addr2 Stmt Source Statement
000000 00000 00004 1 BITS CSECT
000000 4C4D4E4F 2 DC C'<(+|'
TM xx,255-C' ' (X'BF') sets condition code 1 (mixed) for every character in the DC. That is the intention of the loop. I don't know what the corresponding characters code in ASCII; I'm too lazy to check. So what. I live in an EBCDIC world. As proof (of sorts) I wrote this -
Code:
BITS CSECT
USING *,12
SAVE (14,12)
LR 12,15
LA 2,L'CHARS
LA 3,CHARS
MVI CHARS+L'CHARS-2,X'00'
MVI CHARS+L'CHARS-1,C' '
LOOP TM 0(3),255-C' ' TEST THE CHARACTER
IPM 15 LOAD THE CC AND PROGRAM MASK
N 15,=X'30000000' ISOLATE THE CC
STCM 15,B'1000',WA STORE THE CC IN WA
MVC CHAR,0(3) PREPARE
UNPK CHARHEX(3),0(2,3) THE
MVI CHARHEX+L'CHARHEX,C' ' MESSAGE
NC CHARHEX,=X'0F0F'
TR CHARHEX,HEXTAB
UNPK CC(3),WA(2)
LA 0,L'MSG WRITE THE COMPLETED
LA 1,MSG MESSAGE
TPUT (1),(0)
LA 3,1(,3)
BCT 2,LOOP
RETURN (14,12),RC=0
CHARS DC C'<(+|ZZ' THE ZZ IS REPLACED BY OTHER STUFF
CHAR DC C' ',C' '
CHARHEX DC C' ',C' '
CC DC C' '
MSG EQU CHAR,*-CHAR
DC C' '
HEXTAB DC C'0123456789ABCDEF'
DC 0D'0'
LTORG ,
WA DC C' '
DC 0D'0'
END BITS
It produced this output on my terminal.
Code:
< 4C 10
( 4D 10
+ 4E 10
| 4F 10
00 00
40 00
For those too lazy to read and understand the program, the first column is the character, the second column is the hexadecimal representation of the column, the third column is the condition code after the program mask was removed after testing the character with the 255-C' ' mask.
sergeyken, I want to test for blank and null, on purpose.
Joined: 30 Nov 2013 Posts: 917 Location: The Universe
I altered the BITS program to test ASCII characters.
Code:
BITS CSECT
USING *,12
SAVE (14,12)
LR 12,15
LA 2,L'ASCII
LA 3,ASCII
L 1,=AL1(0,0,0,X'FF')
S 1,ASCIIBLANK
STC 1,ASCIIBLANK
*LOOP TM 0(3),255-CA' '
LOOP IC 15,ASCIIBLANK
EX 15,TESTTM
IPM 15
N 15,=X'30000000'
STCM 15,B'1000',WA
UNPK HEX(3),0(2,3)
NC HEX,=X'0F0F'
TR HEX,HEXTAB
UNPK CC(3),WA(2)
NC CC,=X'0F0F'
TR CC,HEXTAB
MVI HEX+L'HEX,C' '
LA 0,L'MSG
LA 1,MSG
TPUT (1),(0),R
LA 3,1(,3)
BCT 2,LOOP
RETURN (14,12),RC=0
TESTTM TM 0(3),*-*
ASCIIX DC CA'<(+! ',X'00'
ASCII EQU ASCIIX,*-ASCIIX
HEX DC C' ',C' '
CC DC C' '
MSG EQU HEX,*-HEX
DC C' '
HEXTAB DC C'0123456789ABCDEF'
DC 0D'0'
LTORG
WA DC C' '
ASCIIBLANK DC 0A(0),3AL1(0),CA' '
END BITS
The commented instruction just before the LOOP label is the TM I really wanted to execute, but the HLASM available to me refused to accept 255-CA' '. That's why I had to construct it by hand using
L 1,=AL1(0,0,0,X'FF')
S 1,ASCIIBLANK
STC 1,ASCIIBLANK
and execute the TM.
Now - obviously this version of BITS could not print the characters, but it did produce this output -
3C 10
28 10
2B 10
21 10
20 00
00 00
sergeyken - You'll notice the TM produced a non-zero condition code for ASCII <(+!, which is not what you claimed before. It did produce a 0 condition code for ASCII blank and null, which was expected.
Joined: 30 Nov 2013 Posts: 917 Location: The Universe
Garry Carroll wrote:
Quote:
255-CA' '
not 255-C' ' ?
Garry
Garry, evidently you were not following the thread or bothered to review the BITS program . I wanted an ASCII blank, not an EBCDIC blank. This ASCII @#$% started out when this sergeyken complained that the ideas behind the EBCDIC TM xxx,255-C' ' loop wouldn't work with ASCII. Since HLASM generates ASCII with DC CA'text', I thought CA'x' would work. Silly me. I PMed maybe 15 years ago this issue, though in a different context and got a reply back, basically, "Forget it." And I forgot that!
There's an interesting article How we got the High Level Assembler available through the CBT tape web site. Evidently IBM has gone back to the same arrogance about improving the Assembler - or even correcting errors - they had with Assembler H.