Page 1 of 1

Bit-wise use of variables explained.

Posted: Sun Jan 16, 2011 11:26 am
by Garth
Short and quick version. (For those already familiar with bit-wise variable usage from other systems and just need to know the ACK equivalent syntax...

You can use the following bit operations (the operators "AND" and "OR") in macros to set/clear individual bits in a variable without affecting other bits in that variable:

ACK syntax for Logical AND
SET <variable> = <variable> & <value>

ACK syntax for Logical OR
SET <variable> = <variable> | <value>

bit 0 - 1
bit 1 - 2
bit 2 - 4
bit 3 - 8
bit 4 - 16
bit 5 - 32
bit 6 - 64
bit 7 - 128

bit 8 - 256
bit 9 - 512
bit 10 - 1024
bit 11 - 2048
bit 12 - 4096
bit 13 - 8192
bit 14 - 16384
bit 15 - 32768


To set a bit in a variable, do a logical OR of that bit's value with the variable. For example, to set bit 3 (value 8) in variable C, do

SET C = C | 8

To clear a bit in a variable, you take that bit's value, subtract it from 255, then "AND" the result to the variable. For example, to clear bit 5 (value 32) in variable B, do

SET B = B & 223 (because 255-32=223)

You can test a single bit in a variable with

IF <variable> & <bit> THEN...

for example, "IF A & 64 THEN 12" will test whether bit
6 (with bit weight/value 64) is set in variable A. If bit 6 is set to 1, execution will jump to line 12, otherwise it will continue on the next line as usual.



Lengthy in depth study of how it works...

LOW/HIGH BYTES

BASICS:
A byte is 8 bits. Zero is counted so 8 bits would be numbered 0-7.

ACK has two sets of variables. First set of "small" variables (A-G and A2-G2) are 8 bit only. Each variable holding just one byte values.

The second set (H-Z and H2-Z2) of "large" variables are stored using two bytes or 16 bits. Here is where we get the concept of a low and a high byte.

As rld explained:
"For the 16 bit variables, you can also consider them as the sum of a 'low byte' and a 'high byte', where each byte is 8 bits. If you look in the ACK source code, this is actually the way these variables are stored internally, such that

variable value = (low byte value) + (high byte value * 256)"

The maximum value that one of these large (16bit or 2 byte variables) can hold is 65535 which is simply 256 multiplied 256 times. Remember to count the zero bit as the first bit so 256 is actually 0-255.

Check out this chart that outlines the binary format. It helped me alot.
http://www.vaughns-1-pagers.com/compute ... s-of-2.htm

THE CHART EXPLAINED IN RELATION TO ACK VARIABLE VALUES:

Notice the exponents in the 2nd column. Each bit of the byte increases the bytes value exponentially by a power of 2.

In the first 8 bits you have exponent 0-7 (that is 8 exponents). In the next 8 bits after that which is bit line number 9-16 you have exponents 8-15 (another 8 exponents).

If you examine these closely you will see that each of powers of 2 in the second set of higher exponents correspond to each of the lower powers of 2 in the first 8 bit set.

Each exponent in the second set is simply the same exponent in the first set plus 8.

First bit in the first byte (or first 8 bits) is base 2 to the power of 0.

The first bit of the second byte (or second set of 8 bits) is base 2 to the power of 8 (0+8).

The second bit of the first byte is 2 to the power of 1.

The second bit of second byte is 2 to the power of 9 (1+8).

We can see another pattern occurring in the third column titled "Binary Bit Weight in Decimal."

The first bit of the first byte has a binary bit weight of 1. The first bit of the second byte (or 9th bit) has a binary bit weight of 256 (or 256 multiplied by 1).

The second bit of the first byte has a binary bit weight of 2.
The second bit of second byte (or 10th bit) has a binary bit weight of 512 (or 256 multiplied 2 times).

1st Byte, 3rd bit = binary bit weight 4
2nd Byte, 3rd bit (or 11th bit) = binary bit weight 1024 (or 256 multiplied 4 times).

And so on increasing exponentially by powers of 2...

Okay final piece of puzzle here.

Now look at the fourth column of the binary chart and the values listed under Decimal. Notice how each number in the decimal column is the sum of all the bit weights to the left and up from it. in other words what you are looking at in the decimal column is the totals if you were to turn on just those bits, or if you were to add the values of just the bits listed up to that point in the chart.

Here is where we can see how values can be obtained by simply switching certain bits on and off. When a bit is off it has no value. When on it has the value of its bit weight. When more than one bit is on you add the bit weights to determine the total binary value for that byte.

For single byte variables you only have 8 bits to look at and add up. For the larger variables you have 2 bytes so 16 bits to add up which could be seen as actually two sets corresponding to the first and second byte or first 8 bits plus the second set of 8 bits.

So we can see by all this here that bit-wise variable values are just following the pattern from this binary chart. Each bit represents a specific binary bit weight which is determined by the powers of 2 column.

And ACK is very simple in that is is limited to just 2 bytes. There are no 3 byte variables. So you can easily memorize not only the pattern here but also the values. Theres only 16 binary weights to remember, or just 8 if you only use the 8 bit variables.

Just remember that each bit has a bit-wise value that never changes. It can be set on or off but it's value never changes. The value of the whole byte is just a total of all the bits that are turned on. If you just want the first bit of a byte turned on there is a total byte value for that. If you want just the last bit turned on there is a total byte value for that. If you want both the first and last bit turned on there is a total byte value for that (just add bit 1 weight to bit 8 value). And any combination of bits will have a different byte value.

For the large variables you are actually adding the total value of one byte to the total value of the second byte to determine the grand total value for that variable.

EDIT: Changed old typo in this post... "1st Byte, 3rd bit = binary bit weight 3" ... to "1st Byte, 3rd bit = binary bit weight 4"[/b]

Posted: Sun Jan 16, 2011 11:37 am
by Garth
And as rld explains:

You can use the following bit operations (the operators "AND" and "OR") in macros to set/clear individual bits in a variable without affecting other bits in that variable:

Logical AND - SET <variable> = <variable> & <value>
Logical OR - SET <variable> = <variable> | <value>

Here's how this works. Focusing on 8-bit variables for simplicity, the value of each bit is

bit 0 - 1
bit 1 - 2
bit 2 - 4
bit 3 - 8
bit 4 - 16
bit 5 - 32
bit 6 - 64
bit 7 - 128

EDIT - BTW, notice that the bit numbers do not correspond to the line numbers in the Powers of 2 Table linked earlier - these bit numbers refer to the exponents in the second column of the table titled powers of 2. And the values of each bit are the binary bit weights in decimal column. ~ Garth

To set a bit in a variable, do a logical OR of that bit's value with the variable. For example, to set bit 3 (value 8) in variable C, do

SET C = C | 8

To clear a bit in a variable, do a logical AND of (255 minus that bit's value) with the variable. For example, to clear bit 5 (value 32) in variable B, do

SET B = B & 223

Posted: Sun Jan 16, 2011 11:56 am
by Garth
Ok so if I understand correctly these bit operators are simply bit-wise addition and subtraction.

The pipe symbol "|" when used with a SET <var> command is for adding the total bit-wise value of the bits you wish to turn on. The AND symbol (or ampersand) "&" when used with the SET <var> command is used to subtract the total value of the bits you wish to turn off.

So this means I can turn off more than one bit at once with the AND operator if I add together their bit-weights?

Another question. Since two bytes can hold words in binary is it possible to use words with these operators to activate whichever bits are used by those words? Then we could have like magic words for bitwise operations! Magic as in much easier to remember and easier to type and read in your code. What about single letters. Can they be plugged into 8-bit variables and used this way?

Posted: Sun Jan 16, 2011 8:48 pm
by rld
Garth wrote:Ok so if I understand correctly these bit operators are simply bit-wise addition and subtraction.

The pipe symbol "|" when used with a SET <var> command is for adding the total bit-wise value of the bits you wish to turn on. The AND symbol (or ampersand) "&" when used with the SET <var> command is used to subtract the total value of the bits you wish to turn off.
We're using them that way, but they're not exactly addition and subtraction.

Logical OR is defined as a bit-by-bit operation, that is, the value of each bit in the result is determined only by the bits in the same position in the two operands. So, for each bit in the result:

bit <n> of result = bit <n> of operand 1 OR bit <n> of operand 2.

So, if you say

SET A = A OR 3

The variable A is both the result (where the resulting value is stored) and one of the operands; the other operand is 3.

You could also say something like

SET A = B OR C

where A is the result storage variable, and B and C are the operands.

So for each bit, the logical OR operation is defined as:

0 OR 0 = 0
0 OR 1 = 1
1 OR 0 = 1
1 OR 1 = 1

The only time you get a 0 out of the OR operation is if both the input bits are 0, hence the name. You will get a 1 for the result if either of the input bits are 1, or if both of them are 1.

This can be used to 'set' bits in a binary variable because if I say

SET A = A OR 4

then we can look at this as

operand 1 (A) = abcdefgh
operand 2 (4) = 00000100

where 'abcdefgh' represents the 8 bits which are set (or not set) in variable A.

Now the interesting thing here is that because of how the OR operation is defined,

bit <n> OR 0 = bit <n>.

That is, for each bit in variable A, if we OR it with 0, it will remain unchanged, or

SET A = A OR 0

will never result in any changes to variable A. If you look at the result table above for the OR operation, we see

0 OR 0 = 0
1 OR 0 = 1

So, the first value represents the bit already set in variable A, while the 0 (the second value) is the other operand. The final value (after the equals sign) is the result.

For all the bits in the second operand that we leave set to zero, variable A remains unchanged, so that:

operand 1 (A) = abcdefgh
operand 2 (4) = 00000100

will give the result

result = abcde1gh

What does this mean? It means that setting a bit to 1 in the second operand will make the bit in that position go to 1 in the result, or it will 'set' the bit to 1.

If the bit is already 1, it will remain at 1.

More than one bit can be set at a time in this manner, so if we do

operand 1 (A) = abcdefgh
operand 2 = 10010100

we will set bit 7 (value 128), bit 4 (value 16) and bit 2 (value 4) to 1, and all other bits will remain unchanged.

Posted: Mon Jan 17, 2011 10:43 am
by rld
Logical AND can be defined similarly, as

0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1

This operation will only return a 1 bit in the result if both bits in the operands are also 1, otherwise it will return 0.

So it can be used to 'clear' bits in a variable as follows. Basically, for each bit position that you don't want to affect in a variable, you set the bit to 1 in the operand. Any bit value ANDed with one remains unchanged:

0 AND 1 = 0
1 AND 1 = 1

which means that if you AND a variable with an operand with all bits set, the variable is unchanged:

SET A = A AND 255

will not change the value of A, and for 16-bit variables:

SET Z = Z AND 65535

will not change Z's value.

To clear one or more bits in the variable, you just clear the corresponding bits in the operand to 0. This will force the bit in the same position of the result to 0.

So,

SET A = A AND 239

A = abcdefgh
239 = 11101111
result = abc0efgh

So we have cleared bit 4 (value 16) to zero, while other bits in the variable A remain unchanged.

Testing bits...

Posted: Mon Jan 17, 2011 4:59 pm
by Garth's Equipment Shop
Ok so it should then be possible to test a bit in an if then statement without having to test all the other bits in the byte or bytes correct? So one line of macro code should be enough to test a certain bit of any variable regardless of whether any of the other bits are on or off. So 8 IF/GOTO statements for 8bit variables, or 16 IF/GOTO statements for 16bit. Ok so what is the syntax for "bit on|true/false" or "bit off|true/false" ?

Posted: Mon Jan 17, 2011 9:43 pm
by Tdarcos
You don't need to do 16 tests to determine which bit is set, you just need to test the bit you are interested in. So you have something like this, where B1 is the variable you want to test and 'bit' is the bit number you want to test from 1 to 16

A = B1 & (bit^2)

A will be 1 if true and zero if false.

Re: Testing bits...

Posted: Tue Jan 18, 2011 8:57 am
by rld
Garth's Equipment Shop wrote:Ok so it should then be possible to test a bit in an if then statement without having to test all the other bits in the byte or bytes correct? So one line of macro code should be enough to test a certain bit of any variable regardless of whether any of the other bits are on or off. So 8 IF/GOTO statements for 8bit variables, or 16 IF/GOTO statements for 16bit. Ok so what is the syntax for "bit on|true/false" or "bit off|true/false" ?
You can test a single bit in a variable with

IF <variable> & <bit> THEN...

for example, "IF A & 64 THEN 12" will test whether bit
6 (with bit weight/value 64) is set in variable A. If bit 6 is set to 1, execution will jump to line 12, otherwise it will continue on the next line as usual.

Posted: Thu Jan 20, 2011 7:12 pm
by Garth's Equipment Shop
Cool thanks guys. Yeah i know you dont need 16 tests if your only interested in 1 specific bit. I was just kind of thinking out loud there but failed to share my complete thought.

The complete thought I had in mind was how many lines of macro code it would take to test a variable for every possible combination of bit-wise values it could have. Assuming that is I am using them all. At first I wasn't thinking it was possible to test each bit separately and so would have to test the whole variable for every combination of values or total bit weight/byte sums, which would mean many many many lines of code. But seing as how we can test a bit separately from the others this reduces the code considerably, to only 16 max. Or just 8 for small/1 byte variables.

Tdarcos what was that carrot symbol you used there? Is that just something you use for notation when laying down syntax rules or does it actually do something in macros?

EDIT:
I originally started this thread for BlueTemplar's benefit because he expressed interest in this subject and seemed to share my hunger for knowledge and understanding of advanced ACK arcana. So is this thread helping you BlueTemplar? If not please share your questions so we can help you.