问题
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