How to use hexadecimal floating point literals in GNU GAS?

雨燕双飞 提交于 2019-12-11 02:21:24

问题


C99 introduced hexadecimal floating point literals as a new code obfuscation technique, e.g.:

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

Can I achieve the same level of obfuscation in my GNU GAS assembly code, or do I have to resort to .byte + manual labor?

You may use this as a testing base:

.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.

If I try e.g.:

    float_1_5: .double 0x1.8e0

GAS 2.30 just happily treats it as 1.8 (approximately since not representable), wonderful behavior!

And the following just fails to assemble, which is at least not as bad:

    float_1_5: .double 0x1.8p0

Error:

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

Can a man control the 52 bits of his IEEE 754 significand in peace?

I've already given up on float literals directly on the .text area... How do I specify immediate floating point numbers with inline assembly?


回答1:


cpp macros + GAS bit manipulation workaround

This is not true hex floating point, but it is a reasonable intermediate between hex floats and writing raw floating point integer constants:

#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)

usage:

.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)

The major annoyance is that you have to get the 52 mantissa bits correct. But once you do the first one it is just a matter of copy pasting it around and changing the bits.

Runnable GitHub upstream with assertions:

  • assembly usage
  • macro definitions


来源:https://stackoverflow.com/questions/52905648/how-to-use-hexadecimal-floating-point-literals-in-gnu-gas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!