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?
答案 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上游: