Assembly 我的ARM汇编代码在32位寄存器中计算0的数量有什么问题
我已经设置好了,所以只要有一个,它就会递减,但它不太管用,我也不知道为什么你的设计思想有点过于复杂,这让你很难正确使用代码。我不知道你到底为什么认为在无符号右移之后进行x>>1Assembly 我的ARM汇编代码在32位寄存器中计算0的数量有什么问题,assembly,count,arm,counter,bit,Assembly,Count,Arm,Counter,Bit,我已经设置好了,所以只要有一个,它就会递减,但它不太管用,我也不知道为什么你的设计思想有点过于复杂,这让你很难正确使用代码。我不知道你到底为什么认为在无符号右移之后进行x>>1
如果您的输入通常会清除一些连续的高位,那么我为这个答案编写的左移位循环是最糟糕的。不清楚您的算法是什么。我不知道blt如何帮你检查一点。我建议你简单地做和r3,r0,1;子r1、r1、r3;LSR0,r0,1;b循环。@Jester:blt可以在左移位后检查符号位,如添加r0、r0、r0/cmp/addlt r1、r1、1。或者更好,使用adds/addmi左移并设置标志,以便在设置位时增加计数器。或者我忘记了non-negative的条件名称,它与减号相反,可以与条件add一起使用来计算零。或者,如果你想在移出所有位后停止循环,你确实需要从32中减去。我认为你可以用一种鬼鬼祟祟、高效的方法来计算零:把寄存器移到一个方向或另一个方向都无所谓;如果设置了进位,则递增计数器,然后在寄存器为零时离开循环。这计算1位的数量,当它们全部移出并计数时停止。然后从32中减去1得到你的答案。@DaveM同意这是一个很好的方法,但一点也不认为这是鬼鬼祟祟的。答案很好。需要注意的是,ROR和RRX确实或可能影响进位标志,因此,如果您的条件依赖于进位标志,则使用右移不起作用这一点并不完全正确,尽管无可否认,它们在这种情况下没有多大用处。这就是说,也许一个RRX和其他代码都经过精心设计,这样在进入RRX时,进位标志就可以保证为零,这样就可以使它工作了…@cooperised:是的,轮换很有趣,但是寄存器永远不会变为零。无论如何,请注意,我说过,如果您正在查看符号位/标志,则LSR无法工作。OP在移位后使用cmp,销毁任何C。因此,是的,LSR将低位移位到进位是好的,在循环退出后使用最后的add或sub。与subc r0、r0、1/lsrs r1、r1、1/bne类似,然后是subc r0、r0、1/ret。或者如果设置了C,则条件的正确名称为true。我知道ARM在某些条件名称上与x86不同。同意。如果您确保每次使用前清除进位标志,则使用RRX时寄存器将变为零。也许不是最可读的代码,但却是可行的:-D
test:
mov r1,#32
loop:
cmp r0, #0
beq done
mov r3, r0
lsr r0, r0, #1
cmp r0, r3
blt sub
b done
sub:
sub r1, r1, #1
b loop
done:
mov r0, r1
mov pc, lr
test:
movs r1, r0 @ copy and set flags
mov r0, #32
@ loop invariants:
@ r0 = return value
@ r1 = input
@ flags set according to the current value of r1
.loop: @ do {
submi r0, r0, #1 @ predicated subtract: if(high_bit_set(r1)) r0--;
adds r1, r1 @ left-shift by 1 and set flags
bne .loop @ keep looping until there are no set bits
@ }while(r1<<=1);
mov pc, lr @ or bx lr