【问题标题】:32 bit PPC rlwinm instruction32 位 PPC rlwinm 指令
【发布时间】:2018-04-02 20:11:43
【问题描述】:

我在理解rlwinm PPC 汇编指令(立即旋转左字然后与掩码)时遇到了一些麻烦。

我正在尝试反转这部分函数

rlwinm r3, r3, 0, 28, 28

我已经知道r3 是什么。 r3 在这种情况下是一个 4 字节的整数,但我不确定这条指令 rlwinm 对它做了什么。

顺便说一句,这是在 32 位机器上。

【问题讨论】:

  • 你看过指令集参考吗?第一个零是移位,两个28 操作数是掩码的开始和结束(这是1 位的序列,所以显然不是值28)。

标签: c++ assembly reverse-engineering instruction-set powerpc


【解决方案1】:

您的理解并不完全正确。根据此说明中的IBM link,您看到的表格是:

rlwinm <target=r3>, <source=r3>, <shift=0>, <begin-mask=28>, <end-mask=28> 

因此不涉及实际的班次。用于AND 操作的实际掩码是由beginend 掩码位置构造的,它不是作为显式参数给出的(a)

在这种情况下,由于两个位置都是 28,因此掩码只是一个位,根据链接页面(稍微解释一下):

如果 begin-mask 值小于 end-mask 值加一,则设置起点和终点之间的掩码位给那些。所有其他位都设置为零。

因此,您看到的指令并不比单个 AND 操作更复杂。


(a)一种允许您指定实际掩码的表单(假设它由连续的一位组成)但它是 四个-参数版本,实际上只是汇编器可以将其转换为五参数之一的语法糖。

【讨论】:

  • 请注意,PowerPC 从 MSB=0 开始计数位,这与其他架构不同。所以 AND 掩码是 C 表示法中的 1U&lt;&lt;(31-28)
【解决方案2】:

@paxdiablo 的回答是正确的,但要添加更多上下文:

各种r* 指令(rlwinm、rlwimi 等)旨在提取其大小在编译时已知的位域,例如 C 结构位域,甚至只是将一个字拆分为字节(使用一个lw 和四个rlwinm 指令而不是几个单独的lbzus)。

lw r4, r3 ; load the word at the address pointed at by r3
rlwinm r5, r4, 8, 24, 31 ; first byte in r5
rlwinm r6, r4, 16, 24, 31 ; second byte in r6
rlwinm r7, r4, 24, 24, 31 ; third byte in r7
rlwinm r8, r4, 0, 24, 31 ; fourth byte in r8, identical to andi r8, r4, 255

rlwinm 指令也可以用作andi 的特殊形式,用于连续的位集。由于 PowerPC 中的指令总是 32 位,因此采用立即数的指令只有 16 位来保存这些值 - 所以如果你想屏蔽一组跨越高/低半字边界的位,比如 23 到 8,你需要使用多个操作。

lis r4, r4, 0x00ff ; first set bits 23 to 16 of the mask
ori r4, r4, 0xff00 ; then bits bits 15 to 8
and r3, r3, r4 ; then perform the actual masking 

但是,使用rlwinm 指令,我们可以在一条指令中执行相同的操作:

rlwinm r3, r3, 0, 8, 23

在您的情况下,该值可能包含某些标志,并且该指令正在提取其中一个标志。下一条指令可能是r3 上的条件分支。

ETA:Peter Cordes 纠正了我的一些错误,对此我表示感谢,并补充说在这种情况下可能没有必要使用 rlwinm,并且可能只是编译器的一个特性导致了这种情况要生成的指令而不是andi

【讨论】:

  • 此外,PowerPC 从 MSB=0 开始计数位,因此对于 32 位计算机,掩码为 1&lt;&lt;(31-28)。在 64 位模式下,第 28 位将位于 64 位寄存器的上半部分,这就是 PowerPC 为 64 位模式提供不同版本的这些指令的原因。 gcc 似乎总是尽可能使用rlwinm,仅当掩码不是一组连续的 1 位时才使用andi
  • 谢谢!它实际上已经有一段时间了,所以我很感激它得到了检查。
  • 如果您有时间,我强烈建议您返回并重写答案中错误的部分,并添加有关 PowerPC 如何编号位的注释。您首先希望答案是正确的,而不是错误的+更正。那么它值得一票,IMO。每个人都可以根据需要查看编辑历史记录,而 SO 的目标是使当前版本的答案尽可能好。
猜你喜欢
  • 1970-01-01
  • 2015-09-02
  • 1970-01-01
  • 2016-08-09
  • 2010-11-08
  • 2011-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多