如何确定是否恰好有两个不同的位?
How to determine if there exactly two different bits?
我是汇编语言的新手,正在尝试检查是否有两个差异 bits.The 原始二进制数是 1111 1111
,我想检查是否正好有两个位是 0前四位如 1010 1111
。我试过了:
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
然后检查r2
的值。有没有更简单的方法来解决这个问题?谢谢!
以下算法的关键思想是使用操作 a & a - 1
清除字中的最低有效设置位。我们执行此操作两次。在第一次之后,我们想要一个非零结果(因此最初至少设置了 2 位),在第二次之后,我们想要一个零结果(因此最初设置了最多 2 位)。回想一下,我们总共有四个位,所以两个清除位意味着已经设置了两个位。
代码如下所示:
@ 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
另一种选择是对 16 种可能的组合使用查找 table。由于微控制器上的内存通常非常快,这可能是个好主意:
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
现在作为进一步的改进,这个查找 table 可以实现为一个位向量:
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
我是汇编语言的新手,正在尝试检查是否有两个差异 bits.The 原始二进制数是 1111 1111
,我想检查是否正好有两个位是 0前四位如 1010 1111
。我试过了:
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
然后检查r2
的值。有没有更简单的方法来解决这个问题?谢谢!
以下算法的关键思想是使用操作 a & a - 1
清除字中的最低有效设置位。我们执行此操作两次。在第一次之后,我们想要一个非零结果(因此最初至少设置了 2 位),在第二次之后,我们想要一个零结果(因此最初设置了最多 2 位)。回想一下,我们总共有四个位,所以两个清除位意味着已经设置了两个位。
代码如下所示:
@ 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
另一种选择是对 16 种可能的组合使用查找 table。由于微控制器上的内存通常非常快,这可能是个好主意:
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
现在作为进一步的改进,这个查找 table 可以实现为一个位向量:
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