!pr2
!lm12
!rm75
Reversing, Getting, and Putting Nybbles....Bob Sander-Cederlof

In the process of de-crypting a large data base, I needed to reverse the nybbles in each of roughly 32000 bytes.  There are probably a lot of ways to do this, but I found one which takes only 12 bytes to reverse the nybbles in the A-register.

Just to be sure we agree on what I am talking about, here is a little diagram:

       a b c d   e f g h



       e f g h   a b c d

One way, sort of brute force, involves breaking the nybbles out and remerging them:

       LDA (PNTR),Y
       ASL             SHIFT EFGH LEFT
       ASL
       ASL
       ASL
       STA TEMP
       LDA (PNTR),Y
       LSR             SHIFT ABCD RIGHT
       LSR
       LSR
       LSR
       ORA TEMP        RE-MERGE NYBBLES
       STA (PNTR),Y

From another perspective, I am trying to rotate the data byte half-way around.  But if I try to do it with ROL or ROR instructions, one bit gets left in CARRY, and an extra bit gets inserted in the middle.  Here is how I finally did it:

       LDA (PNTR),Y    abcd efgh
       ASL             bcde fgh0
       ADC #0          bcde fgha
       ASL             cdef gha0
       ADC #0          cdef ghab
       ASL             defg hab0
       ADC #0          defg habc
       ASL             efgh abc0
       ADC #0          efgh abcd
       STA (PNTR),Y

Each ASL-ADC pair shifts the byte around one bit.  The ASL shifts the leftmost bit into the CARRY bit, and a zero into the right end.  The ADC #0 adds CARRY into the rightmost bit.

Naturally, curiosity forces me to look at the possibility of shifting right one bit also.  We have LSR and ROR, of course, but both of these leave the shifted out bit in CARRY.  I want that bit back in the sign position, like this:

       ABCDEFGH should become HABCDEFG

Two similar methods come to mind, depending on how I might use it.  If the byte to be shifted is in A-reg, and needs to remain there, and I don't want to upset any other registers, I can do it like this:

       PHA     save unshifted value
       LSR     get rightmost bit in CARRY
       PLA     restore unshifted value
       ROR     shift again, putting right bit on left

If the byte to be shifted is in memory, and I want the results to be in memory, I might do it like this:

       LDA FLAG
       LSR        RIGHTMOST BIT INTO CARRY
       ROR FLAG   SHIFT BYTE, PUTTING RIGHT INTO LEFT

Note that I can branch according to the value of the bit which moved around by using BMI or BPL, because that bit is the new sign bit.

The last method above can be useful when you have a program that needs to alternate between two paths.  For example, suppose I write a program to pick up the "next nybble" from a data area.  The first time I call it, I want to get the left nybble of the first byte.  Next time, the right nybble of the same byte.  Next time the left nybble of the next byte.  And so on.

I might store the value $55 in FLAG initially, and then use LDA FLAG, LSR, ROR FLAG, to shift it around.  FLAG will alternate between $55 and $AA.  My subroutine can alternate between left and right nybbles.

Not to leave you hanging, I wrote "get next nybble" and "put next nybble" subroutines.  By the time I finished polishing, yet another technique had surfaced for rotating the $55/$AA flag.  I used this new method so as not disturb the contents of the A-register.

To set up either routine, the address of the beginning of the data area must be put into PNTR and PNTR+1, and $55 must be put into FLAG.



       <<<routines here>>>
