30

我一直想知道某些 CPU 具有的旋转指令的目的是什么(例如,x86 上的 ROL、RCL)。什么样的软件使用这些指令?

我首先认为它们可能用于加密/计算哈希码,但这些库通常是用 C 编写的,它没有映射到这些指令的运算符。(编者注:请参阅C++ 中循环移位(旋转)操作的最佳实践,了解如何编写将编译为旋转指令的 C 或 C++。此外,优化的加密库通常确实具有针对特定平台的 asm。)

有没有人发现它们的用途?为什么他们添加到指令集的位置?

4

6 回答 6

29

跨多个字的位移需要循环。当您对低位字进行 SHL 时,高位会溢出到进位中。要完成该操作,您需要移动高位字,同时将进位带入低位。RCL 是完成此操作的指令。

                      高字 低字 CF
初始 0110 1001 1011 1001 1100 0010 0000 1101 ?
SHL 低字 0110 1001 1011 1001 1000 0100 0001 1010 1
RCL 高位字 1101 0011 0111 0011 1000 0100 0001 1010 0

ROL 和 ROR 对于以(最终)非破坏性的方式逐位检查值很有用。它们也可用于在不引入垃圾位的情况下绕过位掩码。

于 2011-02-12T06:45:46.573 回答
17

旋转移位操作码 ROL、RCL、ROR、RCR)几乎专门用于散列和 CRC 计算。它们非常神秘,很少使用。

移位操作码(SHL、SHR)用于快速乘以 2 的幂,或将低字节移动到大寄存器的高字节。

ROL 和 SHL 之间的区别在于 ROL 获取高位并将其滚动到低位位置。SHL 丢弃高位并用零填充低位位置。

于 2011-02-12T06:44:02.563 回答
9

ROR ROL 是“历史性的”,但在许多方面仍然有用。

在 80386(和操作码 BT)之前,ROL 将被大量用于测试位(SHL 不会传播到进位标志) - 实际上在 8088 中,ROR/ROL 一次只能移动 1 位!!! !

此外,如果您想以一种方式移动,然后以另一种方式移动而不会丢失已移出范围的位,您将使用 ROR/ROL 而不是 SHR/SHL

于 2011-02-12T06:53:13.937 回答
4

如果我理解正确,您的问题是:

“考虑到旋转指令似乎是非常特殊的用途并且不是由编译器发出的,它们何时实际使用以及为什么它们包含在 CPU 中?”。

答案是双重的:

  1. CPU 不是专门为执行 C 程序而设计的。相反,它们被设计为通用机器,旨在使用各种不同的工具和语言解决各种问题。

  2. 语言的设计者没有义务使用 CPU 中的每个操作码。事实上,大多数时候它们不会,因为一些 CPU 指令是高度专业化的,语言设计者没有迫切需要使用它们。

有关按位运算符(以及它们与 C 编程的关系)的更多信息,请参见:http ://en.wikipedia.org/wiki/Bitwise_operation

于 2011-02-12T06:34:32.013 回答
3

回到最初创建微处理器的时候,大多数程序都是用汇编编写的,而不是编译的。大多数 CPU 指令可能不是由编译器发出的(这是创建 RISC 的动力),但通常相对容易在硬件中实现。

图形和密码学中的许多算法都使用旋转,它们包含在 CPU 中使得在汇编中编写非常快速的算法成为可能。

于 2011-02-12T06:46:33.607 回答
1

我认为这里的许多答案都有些倒退,包括目前接受的答案。最大的应用是跨字节/字边界转移数据,广泛用于

  • 提取和插入位模式
    • 协议(从第 6 位开始插入 5 位)
    • 压缩方案(LZW77 及更多)
    • 数据传输(300 波特调制解调器?7 位数据 + 奇偶校验)
  • 任意精度算术
    • 乘以/除以 2 使用旋转进位
    • 乘以/除以 2 的其他幂需要 ROL(或 ROR)
    • 水平滚动 1 位图形

以及利基应用:

  • CRC16/32
  • 密码
  • 无损移动位到符号位或携带测试

从历史的角度来看,移位是昂贵的:当需要将 16 位左移 3 位时,以 8 位为单位(或 128 位以 64 位为单位),ROL 以一次为代价执行两次昂贵的移位:

rotate all bits left by 3
      hi       lo
src = fedcba98|76543210
dst = cba98765|43210---

请注意,位“765”需要右移 5,而位“43210”需要左移 3。这一切都是通过单次旋转完成的,这会将所有正确的位放置到正确的位置,甚至如果它们伴随着错误的位,通过掩码重新组合,这是一种廉价的操作:

dst_lo = ((src_lo ROL 3) & 0b11111000)
dst_hi = ((src_lo ROL 3) & 0b00000111) | (src_hi << 3)

这扩展到 bignum 移动,或将单色图形平面水平滚动任意数量的像素。

这个算法非常重要,以至于 80386 包含了一个双循环指令。

于 2022-01-11T17:25:43.643 回答