__PAIR__ 在 Hex-Rays 反编译器输出中是什么意思?

逆向工程 艾达 反编译器 六线谱
2021-06-13 19:55:43

IDA上的这段代码是什么?我已经发现了几次,我不知道是什么意思。

int a5;
int dGainMax;
COERCE_DOUBLE(__PAIR__(a5, dGainMax))
1个回答

__PAIR__()似乎是一个宏,它根据unsigned long它的两个参数计算一个值,它解释为包含该值的高位和低位。

Guntram 链接的主题-从 IDA PRO Pseudo Decompiler 中了解 __PAIR__ 宏以更好看包含宏的定义及其使用示例,但没有对其进行解释。

// The following definition is not quite correct because it always returns
// uint64. The above C++ functions are good, though.
#define __PAIR__(high, low) (((unsigned long)(high)<<sizeof(high)*8) | low)

宏没有多大意义。它要么被错误地转录(原始包含sizeof(low)而不是sizeof(high)),要么上述伪反编译器仅在它可以工作的情况下使用它。

如果以下条件成立:

  1. CHAR_BIT == 8
  2. sizeof(high) < sizeof(unsigned long)
  3. sizeof(low) <= sizeof(high)

然后该宏可用于从两个寄存器宽度值形成双寄存器宽度的值 - 如 DX:AX。

条件 2 是必要的,因为否则行为将是未定义的(例如,英特尔芯片上的无操作,因为它们屏蔽寄存器 <= 32 位和 31 的移位)。条件 3 是必要的,因为否则“多余”位 inlow可能会溢出high结果值中的位

评论和上下文(用法示例)表明

  1. sizeof(unsigned long) == sizeof(uint64_t)
  2. sizeof(int) == sizeof(int32_t)

这意味着 LP64 种类的编译器,就像通常在 64 位 UNIX 中找到的那些(不是Wintel 平台上常见的 LLP64 类型)。

COERCE_DOUBLE的命名有点不幸,因为它可能是指值转换为双精度值,而“强制”也可能意味着将位重新解释为浮点值,某些编程技巧曾经依赖于此。

此外,关于转换存在一些歧义。x86 FPU 可以将有符号整数直接加载到浮点寄存器 (FILD) 中,但不能将无符号整数加载到浮点寄存器中,这意味着 x86 编译器必须发出大量额外代码来转换无符号整数。

这意味着__PAIR__带有隐含无符号宏可能会错误地暗示不存在的主要低效率,因为每当有符号问题时,x86 CPU 倾向于将双宽度寄存器值解释为有符号(例如,请参阅 CDQ、DIV 或 FILD 等指令) . 魔鬼在被奇怪的宏隐藏和掩盖的细节中。因此,即使反汇编程序的 SP 模拟有时会有些偏差,也建议咨询反汇编程序以了解实际情况。