【发布时间】:2013-03-22 02:57:58
【问题描述】:
所以我之前有一个关于位操作的面试问题。该公司是一家知名的 GPU 公司。我在汇编语言方面的背景很少(尽管是计算机体系结构的博士生,但很奇怪),正如这个叙述所表明的那样,我搞砸了。问题很简单:
“编写一个快速代码,计算 32 位寄存器中 1 的数量。”
现在我正在研究手臂组装。所以很自然地,我再次重新审视了这个问题,并通过研究 ISA 得出了这段代码。
对于你们那里的武装专家来说,这是正确的吗?有没有更快的方法来做到这一点?作为一个初学者,我自然认为这是不完整的。 "xx" 中的 AND 指令感觉是多余的,但是在 ARM isa 中没有其他方法可以移位寄存器...
R1 将包含最后的位数,而 R2 是我们要计数的位的寄存器。 r6 只是一个虚拟寄存器。注释用 () 括起来
MOV R1, #0 (initialize R1 and R6 to zero)
MOV R6, #0
xx: AND R6, R6, R2, LSR #1 (Right shift by 1, right most bit is in carry flag)
ADDCS R1, #1 (Add #1 to R1 if carry flag is set)
CMP R2, #0 (update the status flags if R2 == 0 or not)
BEQ xx (branch back to xx until R2==0)
【问题讨论】:
-
最快的还取决于您希望设置的位数。很少有 1,Kernighan's bit counter 将获胜,因为它为每个位集运行一轮循环。
-
您的算法对所有
1都采用4*32+2指令。 Dave Seal 的算法需要六条指令加上一次内存访问;除非内存非常慢,否则它可能对所有类型的输入都一样快。我怀疑很少有人会得到 Dave Seal 的解决方案。reverse subtract对我来说很奇怪。