如何在GNU GAS中使用十六进制浮点文字?

时间:2018-10-20 12:29:09

标签: floating-point gas

C99引入了十六进制浮点文字作为一种新的代码混淆技术,例如:

assert(0x1.8p0 == 1.5);

我可以在我的GNU GAS汇编代码中实现相同程度的混淆吗,还是必须诉诸.byte +体力劳动?

您可以将其用作测试基础:

.data
    float_1_5: .double 1.5
    float_2_5: .double 2.5
    float_4_0: .double 4.0
.text
.global _start
_start:
    /* 1.5 + 2.5 == 4.0 */
    fldl float_1_5
    fldl float_2_5
    faddp %st, %st(1)
    fldl float_4_0
    fcomip %st(1)

    /* Exit syscall. */
    mov $1, %eax
    mov $0, %ebx
    int $0x80

Here is a more runnable version on GitHub with an assert if you want to test it out

如果我尝试例如:

    float_1_5: .double 0x1.8e0

GAS 2.30只是将其视为1.8(大约无法表示),这是一个很棒的行为!

以下内容无法汇编,至少还不那么糟糕:

    float_1_5: .double 0x1.8p0

错误:

 Error: junk at end of line, first unrecognized character is `p'

一个人可以和平地控制其IEEE 754重要数字的52位吗?

我已经直接在.text区域放弃了浮点文字... How do I specify immediate floating point numbers with inline assembly?

1 个答案:

答案 0 :(得分:1)

cpp宏+ GAS位操作变通方法

这不是真正的十六进制浮点数,但它是十六进制浮点数和编写原始浮点整数常量之间的合理中间点:

#define LKMC_FLOAT_64_SIGN_BITS 1
#define LKMC_FLOAT_64_EXP_BITS 11
#define LKMC_FLOAT_64_MANTISSA_BITS 52
#define LKMC_FLOAT_64_EXP_BIAS ((1 << (LKMC_FLOAT_64_EXP_BITS - 1)) - 1)
#define LKMC_FLOAT_64(sign, exp, mantissa) ((((sign << LKMC_FLOAT_64_EXP_BITS) | exp + LKMC_FLOAT_64_EXP_BIAS) << LKMC_FLOAT_64_MANTISSA_BITS) | mantissa)

用法:

.data
    double_1_5: .quad LKMC_FLOAT_64(0x0, 0x0, 0x8000000000000)
    double_2_5: .quad LKMC_FLOAT_64(0x0, 0x1, 0x4000000000000)
    double_4_0: .quad LKMC_FLOAT_64(0x0, 0x2, 0x0000000000000)

主要的烦恼是您必须正确设置52个尾数位。但是一旦完成第一个操作,就只需复制并粘贴并更改位即可。

带有断言的可运行GitHub上游: