If I wanna re-arrange the bit order of a byte, eg. move the 3rd bit to 1st bit and mov the 2nd bit to 5th bit, what's the optimized way to do that?
Posted on 2003-09-28 00:14:34 by optimus
Maybe like this:


push orderhigh
pop edx
mov ecx,orderlow
again:
shr eax,1
rcl bl,cl
shrd ecx,edx,5
shr edx,5
test cl,31
jnz again
Posted on 2003-09-28 08:34:35 by Sephiroth3
... re-arrange the bit order of a byte, eg. move the 3rd bit to 1st bit ...
Using the above quoted example, is your "re-arranging" intention to simply "replace" the 1st bit by the 3rd bit without changing the content of the 3rd bit, or do you want to "exchange" the content of those 2 bits?

If it's only replacement, you could use the following, which assumes the main value is in EAX:
mov  cl,replacement_bit_number       ;0 based

inc cl
rcr eax,cl ;get that bit value in the C flag
pushfd ;save that C flag
rcl eax,cl ;reinstate the value in EAX
mov cl,bit_number_to_be_changed ;0 based
inc cl
rcr eax,cl ;get rid of that bit value in the C flag
popfd ;retrieve the replacement bit
rcl eax,cl ;done

Raymond
Posted on 2003-09-28 10:18:06 by Raymond
not bad!
but still not too much more efficient than my code.
x86 does not contain any direct bit operation code, right?
Posted on 2003-09-28 12:06:28 by optimus

x86 does not contain any direct bit operation code, right?
BT/BTC/BTS/BTR are the bit instructions.

bt eax,0
rcl edx,1
bt eax,2
rcl edx,1

bt eax,4
rcl edx,1
bt eax,6
rcl edx,1

bt eax,1
rcl edx,1
bt eax,3
rcl edx,1

bt eax,5
rcl edx,1
bt eax,7
rcl edx,1

The above code scrabbles the bits of AL from 76543210 to 02461357 located in DL (upper bits of EDX are changed, EAX is not changed). There is a way to exchange two bits using the parity flag (thanks to Nexo for pointing this out):
i=0

rept 16
test eax,80000000h shr i+1 shl i
jnp @F
xor eax,80000000h shr i+1 shl i
@@: i=i+1
endm
Posted on 2003-09-28 12:11:32 by bitRAKE
that's quite useful!
Posted on 2003-10-14 08:35:28 by optimus
Bitrake,

Nice code. I never thought of that before.
Posted on 2003-10-14 09:28:05 by roticv
There is actually an error in Nexo's code. The Intel manual states the parity flag is only valid for the lower eight bits of the resulting calculation. Additionally, the parity flag is only set when the number of bits set is even in count (0,2,4,8). This macro outlines the constraints of this method:
bitEXCHANGE MACRO memreg:REQ, bit0:REQ, bit1:REQ

LOCAL bitMASK

IF bit0 NE bit1
IF bit0 LT 8 AND bit1 LT 8
bitMASK = (1 SHL bit0) OR (1 shl bit1)

test memreg, bitMASK
jp @F ; nothing to do if the bits are the same
xor memreg, bitMASK ; swap different bits
ENDIF
ENDIF
ENDM


mov al, 080h
bitEXCHANGE al, 7, 5
bitEXCHANGE al, 7, 5

or eax, 020h
bitEXCHANGE eax, 7, 5
Therefor, it is not possible to exchange the bits of a DWORD with this method.
Posted on 2003-10-14 12:09:19 by bitRAKE