!pr1
Two Ways to Merge Fields in a Byte.........Bob Sander-Cederlof

One of the advantages of assembly language is that data can be manipulated easily at the bit and byte level.  This leads to efficiencies in both speed and memory usage which cannot be  matched with most higher-level languages.

We can pack more than one data item into the same byte.  For example, I may use the first three bits of a byte to indicate which of eight colors to use, and the other five bits to indicated position on a 32-pixel line.  There are endless examples.  Since we need to be able to store into and retrieve from bit-fields within bytes, all of the microprocessors include opcodes which make it possible.

To merge two values together which already are "clean", we simply use the ORA opcode.  For example, if I have data for field A in VAL.A as xxx00000 and data for field B in VAL.B as 000xxxxx, I merge them like this:

       LDA VAL.A
       ORA VAL.B

By "clean" I mean that all the bits in VAL.A and VAL.B which are not part of the field values are already zero.  If they are not, then we must first strip out those bits with the AND opcode:

       LDA VAL.A
       AND #$E0
       STA TEMP
       LDA VAL.B
       AND #$1F
       ORA TEMP

There is another way, which is shorter and faster and does not need TEMP.  However, it is harder to figure out why it works.

       LDA VAL.A
       EOR VAL.B
       AND #$1F
       EOR VAL.A

Can you explain it?  I was so unsure of myself when I first ran into this technique that I devised a test program.  My test tries all 256 values of VAL.A and VAL.B, with all possible contiguous fields from 1 bit for VAL.A to 7 bits for VAL.A.  Probably overkill, but it runs in a few seconds.

My program prints out the two field masks for each of the seven field sizes, so that I can tell it is running.  If the two methods for merging get the same results, that is the only output.  If they do not, indicating that one method or the other does not work, I print out more data.

While I was writing the program I tried several variations, such as printing all the results whether they agreed or not.  In order to be able to look at that volume of output reasonably, I added a PAUSE subroutine which enabled me to stop the output by tapping any key, restart it the same way, and abort by tapping the RETURN key.

The code for the first merging method is in lines 1310-1380; that for the second at lines 1400-1450.

The test was conclusive.  I tried every possible combination, and both methods always give the same results.  Looking back, I can see that the whole test was unnecessary; the second method will OBVIOUSLY produce the same results.  Now I see it.  Do you?
