首页 > 解决方案 > ARM 汇编中 32 位字内的高效逐字节轮换

问题描述

假设我们有一个由四个字节组成的 32 位寄存器R = b0|b1|b2|b3

我想做的是计算R'whereR' = (b0 <<< x) | (b1 <<< x) | (b2 <<< x) | (b3 <<< x)x的是任意值并<<<指的是左字节旋转(即10101110 <<< 2 = 10111010)。

在 ARM 汇编中最有效的方法是什么?

标签: assemblyarmbit-manipulation

解决方案


我们可以通过移位实现旋转并屏蔽掉我们不想要的位来获得所需的效果。这给了我们类似 C 代码的东西:

/* byte-wise right rotate */
unsigned brrot(unsigned R, x)
{
    unsigned mask;

    mask = 0x01010100U - (0x01010101U << R);

    return ((x & mask) >> R | (x & ~mask) << (8-R));
}

翻译成 ARM 拇指组件,这应该给我们:

ldr r2, =0x01010101      @ load 0x01010101
sub r3, r2, #1           @ compute 0x01010100
sub r2, r2, r3, lsl r0   @ compute mask
and r3, r1, r2           @ compute x & mask
bic r2, r1, r2           @ compute x & ~mask
lsr r3, r3, r0           @ compute (x & mask) >> R
rsb r0, r0, #8           @ compute 8 - R
orr r0, r3, r2, lsl r0   @ compute (x & mask) >> R | (x & ~mask) << (8 - R)

如果已知进位标志在此序列之前被清除,则可以通过将两个减法替换为来节省一条指令

sbc r2, r2, r3, lsl r0   @ compute mask

推荐阅读