assembly - 计算寄存器中 1 个数的最快方法,ARM 程序集

标签 assembly arm

所以我之前有一个关于位操作的面试问题。该公司是一家知名的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/

相关文章:

macos - 手工制作的 macOS 可执行文件

sqlite - fatal error : sqlite3. h:没有那个文件或目录

c - 如何为 gcc 内联汇编获取 64 位整数的低位和高位 32 位? (ARMV5平台)

assembly - 如何确定可执行文件中反汇编代码的位置?

c - 从管理员权限应用程序读取 cpu 控制寄存器的值 (Windows)

c++ - 比较 Fortran 和 C++ 汇编程序的 int = floor(sqrt(...))

c++ - ARM 海湾合作委员会 : Conflicting CPU architectures

gcc - 如何链接到外部 THUMB 代码?

optimization - llvm 使用库函数进行优化

assembly - 如何修复 “error:cannot generate COM file, stack segment present”?