SWAP routines for Words, Bytes and Nibbles (nybbles)

AllyCat

Senior Member
Hi,

PICaxe Basic doesn't have an operator to exchange the two nibbles within a single Byte and also the resident SWAP (byte exchange) function is rather inefficient - about twice the number of Program bytes and double the execution time of the snippet below.

Firstly, the two nibbles within a Byte can be exchanged in a "one liner" which (in its byte assignment form) uses only about 8 bytes of Program space and executes in around 1500 PIC instruction cycles (i.e. 1.5 ms @ 4 MHz) :
Code:
b1 = b1 * 257 / 16                ; Exchange the nibbles within any byte
OR
w1 = b1 * 257 / 16 & 255     ; Exchange the nibbles within the (or low) byte
Note that the first version relies on truncating the PICaxe's 16-bit "internal" calculation back to 8 bits, so the result cannot be assigned directly to a Word variable. A Word can of course be assigned from the Byte result, or an "AND $FF" appended as shown in the second example.
---------

Two Bytes (or Words) can be easily swapped via a third variable, or by using PICaxe Basic's SWAP command, but the following doesn't need another variable and almost halves the Program memory and execution time used by the resident command.
Code:
; Fast SWAP (i.e. exchange) of two words or bytes, without using an additional variable.
w1 = w1 XOR w2
w2 = w2 XOR w1
w1 = w1 XOR w2
  AND
b1 = b1 XOR b2
b2 = b2 XOR b1
b1 = b1 XOR b2
The number of Program bytes and the execution time are similar to those of the nibble-swap routine above (and of the "additional variable" version). The nature of the XOR function is such that, for example, the second line can be written as "w2 = w1 XOR w2", but this will run slower and use more Program bytes !

Swapping the two Bytes within a single Word is of course just a "special case" of swapping any two Byte variables as above, but cannot be used with the 8 additional S_Wn "system" variables.

EDIT: Unlikely to be an issue in PICaxe style programs, but worth noting that this "trick" does not work if attempting to exchange a variable (not its value) with itself, e.g. the equivalent of SWAP b1 , b1 .

Cheers, Alan.
 
Last edited:

hippy

Technical Support
Staff member
It is probably worth pointing out the 'three XOR' swap also works with bit variables as well, will work with all 32 bit variables regardless of which word or byte variables those bits are a part of -
Code:
b0 = %11110000
SerTxd( #bit7,#bit6,#bit5,#bit4," ",#bit3,#bit2,#bit1,#bit0, CR, LF )
bit6 = bit6 Xor bit1
bit1 = bit6 Xor bit1
bit6 = bit6 Xor bit1
SerTxd( " |     |    6 <--> 1", CR, LF )
SerTxd( #bit7,#bit6,#bit5,#bit4," ",#bit3,#bit2,#bit1,#bit0, CR, LF )
bit4 = bit4 Xor bit3
bit3 = bit4 Xor bit3
bit4 = bit4 Xor bit3
SerTxd( "   | |      4 <--> 3", CR, LF )
SerTxd( #bit7,#bit6,#bit5,#bit4," ",#bit3,#bit2,#bit1,#bit0, CR, LF )
Code:
1111 0000
 |     |    6 <--> 1
1011 0010
   | |      4 <--> 3
1010 1010
This can be useful if one is mapping 'not in bit order' input or output bits to binary values.
 
Top