所以我之前有一个关于位操作的面试问题。该公司是一家知名的GPU公司。我在汇编语言方面的背景很少(尽管我是计算机体系结构的博士生,但很奇怪),正如这个叙述所表明的那样,我把它搞砸了。问题很简单:
“编写一个快速代码,计算 32 位寄存器中 1 的数量。”
现在我正在研究 ARM 组装。所以很自然地,我再次重新审视了这个问题,并通过研究 ISA 提出了这个代码。
对于您那里的 ARM 专家,这是正确的吗?有没有更快的方法来做到这一点? 作为初学者,我自然认为这是不完整的。 “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)
最佳答案
此代码是否快取决于处理器。可以肯定的是,它在 Cortex-A8 上不会很快,但在 Cortex-A9 和更新的 CPU 上可能运行得非常快。
然而,这是一个非常简短的解决方案。
期望在 r0 中输入,并在 r0 中返回输出
vmov.32 d0[0], r0
vcnt.8 d0, d0
vmov.32 r0, d0[0]
add r0, r0, r0, lsr #16
add r0, r0, r0, lsr #8
and r0, r0, #31
主要工作在vcnt.8 instruction中完成它计算 NEON 寄存器中每个字节的位数,并将位数存储回 D0 的字节中。
没有
vcnt.32
表格,仅 .8
,因此您需要将 4 个字节水平添加在一起,这就是其余代码正在执行的操作。
关于assembly - 计算寄存器中 1 个数的最快方法,ARM 程序集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15736602/