assembly - ARM 汇编中 32 位字内的高效逐字节轮换
问题描述
假设我们有一个由四个字节组成的 32 位寄存器R = b0|b1|b2|b3
。
我想做的是计算R'
whereR' = (b0 <<< x) | (b1 <<< x) | (b2 <<< x) | (b3 <<< x)
指x
的是任意值并<<<
指的是左字节旋转(即10101110 <<< 2 = 10111010
)。
在 ARM 汇编中最有效的方法是什么?
解决方案
我们可以通过移位实现旋转并屏蔽掉我们不想要的位来获得所需的效果。这给了我们类似 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
推荐阅读
- apache-camel - CamelContext 不断重启和关闭
- c++ - 从 C++ 中的 SO 库返回模板化容器
- c# - 使用 Json.NET 将嵌套的 Firebase 数据库对象转换为 C# 对象
- c# - 对两个 ulong 进行或运算时,“在符号扩展的操作数上使用按位或运算符”
- python-3.x - Python-运行时错误(NZEC)
- excel - Excel 中的 Python 输出
- python-3.x - 将数据帧转换为张量二进制或字符串错误
- mysql - 使用 Spring Data 时外键约束失败
- sql-server - 如果插入的记录包含文本,则 - TSQL
- docker - 如何使用项目解决方案创建 docker 容器,其中 lib 项目位于比构建上下文高一级的位置