MMCC MASTHEAD
Mid-Michigan Computer Consultants - Bay City, Michigan
 


CONTENTS       (old style)
Mid-Michigan Computer Consultants
509 Center
Bay City, Michigan

Sales (989) 892-9242
Support (989) 686-8860

Plb-0850.cfm v1.0


plb-t010.cfm
 

ANSI Standard PL/B Language and Visual PL/B

Binary Logic



When someone mentions "binary logic" or "bit masks" or even "hex notation", most programmers will groan. Nobody but the hard core hackers and systems types deal with that stuff any more! It's for the "C" jockies and the folks in Redmond.

In the 1960's and 1970's it was different. Everyone could deal with binary code. Programmers suffered with 200 page printed memory dumps in HEX on a daily basis. Many could do hex and binary arithmetic as easily as they could decimal.

(If you are of a certain age you may well remember the infamous and invaluable "IBM Green Card". An 8½x22 inch card folded into 12 pages to fit the shirt pocket. It had tables for everything you might need to live in the decimal, hex, binary, EBCDIC, and punch card world)

Today's modern languages and visual programming tools have eliminated most of the need to deal with binary or hex data. But it's still there at the core of everything we do and there are times when it's really useful.

So why is it used at all. Mainly because it's the native tongue of the computer. Everything under the covers is done at the binary level. For systems programmers, "bit flags" provide a super compact, fast and efficient way to control data. For them the "bit mask" is often the tool of choice.

The BIT MASK



For the purposes of this discussion we're going to use the PL/B GETFILE instruction and the FILETYPE keyword. This is a version 9.x feature of the language.
    OPEN     ISIFILE, "filename"
    GETFILE  ISIFILE, FILEFORMAT={nvar}
The GETFILE instruction will return a single 8-bit byte. Each bit in that byte has a meaning. The following table shows the bits and their representation as DECIMAL, HEX, and BINARY numbers:
 dec   hex      binary    Meaning
   1   0x1    0000 0001   IFILE
   2   0x2    0000 0010   AFILE
   4   0x4    0000 0100   -----
   8   0x8    0000 1000   -----
  16   0x10   0001 0000   version 9.0x format
  32   0x20   0010 0000   version 8.7x format
  64   0x40   0100 0000   the ISI file supports file larger than 4BG.
 128   0x80   1000 0000   -----
As an example let's use an IFILE indexed under the version 8.7x runtime. The bit mask for that would be:
  33   0x21   0010 0001   IFILE and Version 8.7x
The PL/B language does a lot for the programmer by converting values to match the coding the programmer is using. In the case of the FILEFORMAT, the return variable needs to be a {nvar} or "numeric variable".

In this case the {nvar} can be a FORM field or an INTEGER. PL/B will convert the one byte bitmask to the type of variable you specifiy. A FORM field needs to be 3 bytes wide to accept a decimal number from 0 to 255. An Integer can be one byte because it will be a binary number of 8 bits (0 to 255).

TESTING THE BIT MASK


OK, we have the fileformat byte now. What can we do with it.

First, if you're looking for a very specific configuration (AFILE indexed with 9.0 and supporting large files) you could figure out the decimal equivalent of the bits and test that value:
  82   0x52   0101 0010   IFILE and Version 8.7x
You can now simply say IF (FILETYPE = 82). This will work if the you're using an INTEGER or a FORM variable.

Of course most of the time you'll want to be more specific. Say you just want to know if the file is an IFILE or not. Or you know it's an IFILE and you just need to know how it was indexed.

Testing single bits (or combinations of bits) can be done with binary logic using the binary AND instruction. This is the part everyone hates because it gives them a headache to think about it, but it's really pretty easy.

The AND instruction works at the bit level. It takes two bytes, or two equal length strings of bytes, and logically adds the bits together without a carry. The "truth table is":
      0  +  0  =  0
      0  +  1  =  0
      1  +  0  =  0
      1  +  1  =  1
The AND instruction returns the results via the ZERO and EOS flags.
        If either string is nul the EOS is set.
        If NO bits produce a 1 the ZERO flag is set.

So to test a pair of bytes you can say
      AND   TEST_MASK,  FILETYPE
      IF NOT ZERO
         .... test was true, the bit you tested is SET
      ENDIF
To be more practical let's use an example. We will test an ISI file to see which version it was indexed with. The only bits we want to test are:
 dec   hex      binary    Meaning
   1   0x1    0000 0001   IFILE
   2   0x2    0000 0010   AFILE
We start by doing the GETFILE. We could use a FORM variable or an INTEGER variable. If we use the FORM we'll need a 3 byte number. We'll then need to convert that to a one byte integer, or a one byte string. (The AND will work against either INTEGER or DIM variables). By using an integer we'll get a one byte binary number immediately.

NWK03       FORM     3
INT_WORK    INTEGER  1
IFILE_MASK  INIT     0x1
AFIlE_MASK  INIT     0x2

      GETFILE  ISIFILE, FILEFORMAT=NWK03    ;Example 1 using FORM variable
      MOVE     NWK03,   INT_WORK            ;Convert 3 bytes number to 1 byte integer
      AND      IFILE_MASK, INT_WORK         ;Do the AND
      IF ZERO                               ;Test zero flag
          DISPLAY  "bit was NOT set"
        ELSE
          DISPLAY  "bit IS set"
      ENDIF

      GETFILE  ISIFILE, FILEFORMAT=INT_WORK ;Example 1 using INTEGER variable
      AND      IFILE_MASK, INT_WORK         ;Do the AND
      IF ZERO                               ;Test zero flag
          DISPLAY  "bit was NOT set"
        ELSE
          DISPLAY  "bit IS set"
      ENDIF
NOTE: the AND instruction is destructive. It combines the bits into the second operand. You'll need to refresh that second operand if you do more than one AND or if you intend to use the second operand for anything else.

The language provides a TEST instruction that does the AND but is non-destructive. Both operands are left unchanged.

VARIATIONS


There are a number of ways to specify the mask to be used with the AND. It can be an EQUATE, or a literal, or a variable. For example all of the following work:
INTMASK    INTEGER   1       ;No value... you have to move something
BYTE_1     INIT      0x1
B_EQU_1    EQU       0b00000001
B_DEF_1    DEFINE    1

        AND     0b00000001,  INT_WORK
        AND     0x1,         INT_WORK
        AND     B_EQU_1,     INT_WORK
        AND     B_DEF_1,     INT_WORK
		
        CALC    INTMASK = (1)
        MOVE    "1",         INTMASK
        AND     INTMASK,     INT_WORK

COMBINING ATTRIBUTERS


The PL/B language has the ability to combine bit masks using most of the definition types shown above. This can be interesting and useful. It's best used when you have defined your bit masks by name and want to combine several. For example:
MASK_IFILE    EQU    0x1
MASK_AFILE    EQU    0x2
MASK_VER_9    EQU    0x16
MASK_VER_87   EQU    0x32
MASK_LARGE    EQU    0x64
INTMASK       INTEGER   1       ;No value... you have to move something

          CALC  INTMASK = (MASK_IFILE + MASK_VER_9)
          AND   INTMASK,  FILETYPE
          IF NOT ZERO
              DISPLAY "ISI file AND/OR version 9"
          ENDIF
In this example notes that the AND instruction will set the zero flag only if NONE of the bits match. If ANY of them match you get the not zero.

If you want a combined flag to test for ALL bits set use one of the other logical operations, OR, XOR, NOT AND, etc. You'll have to decide which si the best to use.

PLBEQU.INC SUNBELT DEFINED ATTRIBUTES


Sunbelt pre-defines many of the bit strings in the PLBEQU.INC include unit. These will show up in the language reference. This makes it possible to use the names without worrying about the specific bit configuration. We recommend looking at the definitions and understanding exactly what they are.

OPINION


Most of the Sunbelt documentation, and that for other systems too, tend to use the hex notation for bit flags. We've used that through this discussion. But we've also shown the binary representation in many cases.

In our opinion, a programmer would be well served by using the binary constructions. We work in what's called a "visual" programming environment. HEX notation is not visual. BINARY is.

Our preference for defining the FILETYPE bits would be this:
       0  0  0  0        0  0  0  0
       |  |  |  |        |  |  |  |-- IFILE
       |  |  |  |        |  |  |----- AFILE
       |  |  |  |        |  |--------
       |  |  |  |        |-----------
       |  |  |  |-------------------- version 9.0x 
       |  |  |----------------------- version 8.7x
       |  |-------------------------- large file support
       |-----------------------------
  OR
       0  0  0  0        0  0  0  1   IFILE
       0  0  0  0        0  0  1  0   AFILE
       0  0  0  1        0  0  0  0   version 9.0x
       0  0  1  0        0  0  0  0   version 8.7x
       0  1  0  0        0  0  0  0   large file support

       AND   0b00000001,  FILETYPE    ;Test for IFILE
       AND   0b00000010,  FILETYPE    ;Test for AFILE
       AND   0b00010000,  FILETYPE    ;Test for version 9.0x
       AND   0b00100000,  FILETYPE    ;Test for version 8.7x   



v1.10

Write to MMCC Technical Support at:               Send e-mail to MMCC.
MMCC - Technical Support
600 W. Midland
Bay City, MI 48708
(989) 686-8860
© 1997 - 2024 MMCC - All Rights Reserved