我有一个小型 C++ 32 位应用程序,具有以下变量赋值:
double unknown = -4.656612875e-10;
我想了解这是如何在汇编中表示的。显然它在 xmm0 中表示为
0xbe000000001c5f68
。
为了验证,我现在添加这一行:
double unknown1 = 0xbe000000001c5f68;
我原以为它会产生完全相同的组件,但结果不同。
double unknown = -4.656612875e-10;
004F2265 movsd xmm0,mmword ptr [__real@be000000001c5f68 (04F9BE8h)]
004F226D movsd mmword ptr [unknown],xmm0
double unknown1 = 0xbe000000001c5f68;
004F2272 movsd xmm0,mmword ptr [__real@43e7c0000000038c (04F9B40h)]
004F227A movsd mmword ptr [unknown1],xmm0
我必须为
unknown1
分配什么十六进制值,以便汇编等于 unknown
?
0xbe000000001c5f68
与整数文字 13690942867208167272
相同,因此您的 unknown1
被初始化为该值(与 -4e10
相差甚远,它的顺序为 1e19
)。
您在程序集中看到的是
-4.656612875e-10
具有与 0xbe000000001c5f68
(BE 00 00 00 00 1C 5F 68
) 相同的八个字节的对象表示形式。您可以转换类型,同时保留对象表示,使用 std::bit_cast
重新解释这些位:
double unknown1 = std::bit_cast<double>(0xbe000000001c5f68u);
一般来说,这称为“类型双关”:保持对象表示不变。正常转换和强制转换保持表示的值相同或尽可能接近(例如,将双精度数截断为整数,或将大整数四舍五入为最接近的可表示双精度数)。
还有十六进制浮点文字,如下所示:
double unknown2 = -0x1.00000001c5f68p-31;
但它与对象表示并不一对一匹配。您可以看到尾数字段实际上是十六进制形式,但二进制 64 的前 12 位(符号和指数字段)是
(e + 1023) | (negative ? 0x800 : 0)
。对于此数字,(-31 + 1023) | 0x800 == 0xbe0
,前 3 个十六进制数字。