IDA 反编译宏

逆向工程 艾达 六线谱 反编译器 漂浮
2021-07-01 16:11:46

下面的 Hex Rays 反编译代码中的宏COERCE_FLOATCOERCE_UNSIGNED_INT的目的是什么

double __cdecl sub_401580(float a1)
{
  unsigned int v1; // eax@1
  double v2; // st7@1
  float v4; // [sp+10h] [bp+4h]@1
  float v5; // [sp+10h] [bp+4h]@1

  v1 = LODWORD(a1) & 0x80000000;
  v4 = 1.273239493370056 * a1 - a1 * 0.4052847325801849 * COERCE_FLOAT(LODWORD(a1) & 0x7FFFFFFF);
  v2 = v4;
  v5 = v4 * v4;
  return (float)(v5
               * ((v5 * COERCE_FLOAT(v1 ^ COERCE_UNSIGNED_INT(-0.0032225901))
                 + COERCE_FLOAT(v1 | COERCE_UNSIGNED_INT(0.015124941)))
                * v5
                + COERCE_FLOAT(v1 | COERCE_UNSIGNED_INT(0.20363937)))
               + v2 * 0.7844448685646057);
}
3个回答

COERCE_TYPE(x)是一样的*(TYPE *)&xHex-RaysCOERCE_...&x非法使用例如:

COERCE_DOUBLE(__PAIR__(i1,i2))

与 相同*(double *)&__PAIR__(i1, i2),但由于&不能应用于调用,我们最终看到了COERCE

它的名字正确地传达了它的意思。

我会读这个(可能是一个错误),因为将变量的二进制内容视为另一种类型的变量,如下所示:

  • coerce float is *((float*)&var),其中 var 的大小与 float 相同,应该是 4 个字节。
  • coerce unsigned int is *((unsigned int*)&var),其中 var 与 unsigned int 的大小相同。

据我所知,32 位平台将 unsigned int 和 float 视为 4 个字节长度的值。

coerce_* 函数通常比简单的转换更具强制性,我认为它们的含义如下:

   #define VALUE_SIZE (sizeof(int))

struct VALUE_TYPE {
    char contents[VALUE_SIZE];
};

struct VALUE_TYPE COERCE_FLOAT(float arg) {
    struct VALUE_TYPE rv;
    memcpy(&arg, rv.contents, sizeof arg);
    return rv;
}

struct VALUE_TYPE COERCE_INT(int arg) {
    struct VALUE_TYPE rv;
    memcpy(&arg, rv.contents, sizeof arg);
    return rv;
}

struct VALUE_TYPE COERCE_UNSIGNED_INT(unsigned int arg) {
    struct VALUE_TYPE rv;
    memcpy(&arg, rv.contents, sizeof arg);
    return rv;
}

来源:https : //stackoverflow.com/a/37198532/912236

使用它们的原因可能与 ABI 如何传递浮点数和如何传递整数有关。Windows 32 位代码(stdcall 或 cdecl)没有区别,但在 x64 中浮点数和整数在不同的寄存器中传递。

这些宏可能对 32 位目标的编译没有影响,只是为了确保(或通知读者/编译器)预期类型,但这纯粹是我的猜测。