floating-point - 逆向工程未知浮点格式

标签 floating-point reverse-engineering ieee-754 ieee

我正在尝试对一些旧文件格式(Cinema4D 旧版本)进行逆向工程,但我找不到其规范。
在这种文件格式中,我设法发现浮点值存储为四个字节,但它们似乎不是正常的 IEEE 格式,这不是字节序问题。我最近花了很多时间使用 hex<->float 转换工具来解决这个问题。
以下是一些示例值:

0     = 00 00 00 00
1     = 80 00 00 41
2     = 80 00 00 42
4     = 80 00 00 43
8     = 80 00 00 44

0.25  = 80 00 00 3F
16384 = 80 00 00 4F
我从上面两行的观察是,从 3F 到 4F 时,似乎有东西环绕在这里
1.5  = C0 00 00 41
2.5  = A0 00 00 42

-1   = 80 00 00 C1
-1.5 = C0 00 00 C1
-2   = 80 00 00 C2
-3   = C0 00 00 C2
所以,这里有一些观察:
  • 增加最后一个字节 +1,使值加倍
  • 如果设置了最后一个字节的高位,则数字为负
  • 第一个字节处理非整数值

  • 尽管有一些明显的模式,并且有一些指数/尾数,但我无法弄清楚这一点。也许我什至遗漏了一些明显的东西,这是正常的 IEEE ?弄清楚尾数/指数等有多少位不是问题(在上面的示例中,两个中间字节为零),首先我需要找出获得浮点值的公式

    最佳答案

    这里的线索是Cinema 4D在 Commodore Amiga 平台上首次亮相,该平台使用 FFP 浮点格式,该格式似乎是为简单的软件仿真而设计的。在Amiga ROM Kernel Reference Manual的第35章中有解释。 :

    The mantissa is considered to be a binary fixed-point fraction; except for 0, it is always normalized (the mantissa is shifted over and the exponent adjusted, so that the mantissa has a 1 bit in its highest position). Thus, it represents a value of less than 1 but greater than or equal to 1/2.


    The exponent is the power of two needed to correctly position the mantissa to reflect the number's true arithmetic value. It is held in excess-64 notation, which means that the two's-complement values are adjusted upward by 64, thus changing $40 (-64) through $3F (+63) to $00 through $7F


    The value of 0 is defined as all 32 bits being 0s


    尾数位存储在最高有效的三个字节中,而最低有效字节由其最高有效位中的符号位和最低有效六位中的偏置指数组成。除零外,32 位数字的数值 x因此是 (-1)x<7> * (x<31:8>/224) * 2(x<6:0> - 64)。
    基于此,下面的ISO-C99代码提供了一个函数decode_ffp()返回以无符号 32 位整数形式提供的 FFP 浮点数的数值。请注意,伪零和非规范化编码的行为未定义,因为官方文档没有说明应如何处理它们。
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <math.h>
    
    float decode_ffp (uint32_t a)
    {
        const uint32_t FFP_EXPO_BIAS = 64;
        const uint32_t FFP_MANT_BITS = 24;
        const uint32_t FFP_EXPO_BITS = 7;
        const uint32_t FFP_EXPO_MASK = (1 << FFP_EXPO_BITS) - 1;
        uint32_t mant = a >> (FFP_EXPO_BITS + 1);
        uint32_t sign = (a >> FFP_EXPO_BITS) & 1;
        int32_t expo = (a & FFP_EXPO_MASK) -  FFP_EXPO_BIAS;
        float val;
    
        if (a == 0) {
            val = 0.0f;
        } else {
            val = exp2f (expo) * mant / (1 << FFP_MANT_BITS);
            val = (sign) ? (-val) : val;
        }
        return val;
    }
    
    int main (void)
    {
        uint32_t test_vec[] = {
            0x00000000,
            0x80000041,
            0x80000042,
            0x80000043,
            0x80000044,
            0x8000003F,
            0x8000004F,
            0xC0000041,
            0xA0000042,
            0x800000C1,
            0xC00000C1,
            0x800000C2,
            0xC00000C2
        };
        int num_test_vec = sizeof test_vec / sizeof test_vec[0];
    
        for (int i = 0; i < num_test_vec; i++) {
            printf ("%08x ==> % 15.8e\n", test_vec[i], decode_ffp (test_vec[i]));
        }
        return EXIT_SUCCESS;
    }
    

    关于floating-point - 逆向工程未知浮点格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34773505/

    相关文章:

    iphone - iPhone 设备上的 gdb 未在断点处停止

    在jasper报告中以指定格式显示浮点值的java代码

    c++11 - 有符号、无符号和浮点类型之间的转换如何进行?

    python - 将 float 转换为字符串,并在 Python 中的点后切割零位小数

    c# - 浮点精度

    wolfram-mathematica - 阅读已定义函数的代码(尤其是从 System` 上下文中)的最佳方法是什么?

    debugging - 使用 IDA PRO 6.1 调试 x64 应用程序

    floating-point - 第一个(最小的)偶数不能用 IEEE 754 float 表示?

    在 C 中将 32 位和 64 位数字转换为 IEEE 754 二进制

    c - 融合乘加和默认舍入模式