IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

The Test under Mask (TM) Instruction


IBM Mainframe Forums -> PL/I & Assembler
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
steve-myers

Active Member


Joined: 30 Nov 2013
Posts: 917
Location: The Universe

PostPosted: Sat Jan 05, 2019 2:36 pm
Reply with quote

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.
Back to top
View user's profile Send private message
sergeyken

Senior Member


Joined: 29 Apr 2008
Posts: 2137
Location: USA

PostPosted: Sun Jan 06, 2019 12:37 am
Reply with quote

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 '&cent' 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?
Back to top
View user's profile Send private message
steve-myers

Active Member


Joined: 30 Nov 2013
Posts: 917
Location: The Universe

PostPosted: Sun Jan 06, 2019 8:20 am
Reply with quote

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 '&cent' 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 '&cent' will be considered as "space-equivalent".
Not one of those characters are considered as white space by any processing program I'm aware of.
Back to top
View user's profile Send private message
sergeyken

Senior Member


Joined: 29 Apr 2008
Posts: 2137
Location: USA

PostPosted: Mon Jan 07, 2019 9:15 am
Reply with quote

steve-myers wrote:

- even in EBCDIC table, the legal characters '<', '(', '+', '|', and '&cent' 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.
Back to top
View user's profile Send private message
steve-myers

Active Member


Joined: 30 Nov 2013
Posts: 917
Location: The Universe

PostPosted: Mon Jan 07, 2019 10:32 am
Reply with quote

sergeyken wrote:
steve-myers wrote:

- even in EBCDIC table, the legal characters '<', '(', '+', '|', and '&cent' 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.
Back to top
View user's profile Send private message
steve-myers

Active Member


Joined: 30 Nov 2013
Posts: 917
Location: The Universe

PostPosted: Mon Jan 07, 2019 9:16 pm
Reply with quote

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.
Back to top
View user's profile Send private message
Garry Carroll

Senior Member


Joined: 08 May 2006
Posts: 1205
Location: Dublin, Ireland

PostPosted: Tue Jan 08, 2019 1:39 pm
Reply with quote

Quote:
255-CA' '


not 255-C' ' ?

Garry
Back to top
View user's profile Send private message
steve-myers

Active Member


Joined: 30 Nov 2013
Posts: 917
Location: The Universe

PostPosted: Tue Jan 08, 2019 4:43 pm
Reply with quote

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.
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> PL/I & Assembler

 


Similar Topics
Topic Forum Replies
No new posts NI AND IMMEDIATE instruction PL/I & Assembler 2
No new posts Zunit Test case editor error Testing & Performance 4
No new posts Want to mask Middle 8 Digits of Debit... COBOL Programming 3
No new posts Assembler: Set Program Mask for decim... PL/I & Assembler 4
No new posts Copying GDG version(all/few) from pro... CLIST & REXX 13
Search our Forums:

Back to Top