I'm new to assembly language, and trying to check if there are two diff bits.The original binary number is 1111 1111
,and I wanna check if there are exactly two bits are 0 in first four bits like 1010 1111
. And I tried:
mov r1,#4 ;count for first four bits
mov r2,#0 ;count for diff bit
ldr r4,=0xAF ;the number that need to check
mov r4,r4,lsr #4
count
ldr r3,=0x1
and r3,r4
cmp r3,#1
bne notDiff
add r2,#1
notDiff
mov r4,r4,lsr #1
subs r1,#1
bne toEnd
b count
toEnd
fin b fin
Then check the value of r2
. Is there an easier way to address this issue?Thanks!
The key idea for the following algorithm is to use the operation a & a - 1
which clears the least significant set bit in a word. We perform this operation twice. After the first time, we want a nonzero result (so at least 2 bits had been set originally) and after the second time, we want a zero result (so at most 2 bits had been set originally). Recall that we have four bits in total, so two clear bits means that two bits have been set.
Code looks like this:
@ assumes input in R4
@ increments R2 if there exactly two bits are set
count: and r4, r4, #0xf0 @ clear out all but the four bits we want to check
sub r0, r4, #1 @ r0 = r4 - 1
ands r0, r4, r0 @ r0 = r4 & (r4 - 1)
bxeq lr @ if r0 == 0, we had 0 or 1 bit set: ignore
sub r1, r0, #1 @ r1 = r0 - 1
tst r1, r0 @ r0 & (r0 - 1)
addeq r2, r2, #1 @ if the result was zero, we had 2 bits set
@ so go ahead and increment r2
bx lr
An alternative option is to use a look up table for the 16 possible combinations. As memory is usually quite fast on a micro controller, this might be a good idea:
count2: adr r0, #lut @ load look up table address
ldrb r0, [r0, r4, lsr #4] @ fetch result from look up table
add r2, r2, r0 @ add result to R2
bx lr
lut: .byte 0, 0, 0, 1
.byte 0, 1, 1, 0
.byte 0, 1, 1, 0
.byte 1, 0, 0, 0
Now as a further improvement, this look up table can be implemented as a bit vector:
count3: ldr r1, =0x16680000 @ load look up table
mov r0, r4, lsr #4 @ compute look up table index
movs r0, r1, lsl r0 @ move desired LUT bit into N flag
addmi r2, r2, #1 @ increment r2 if N bit set
bx lr