assembly 用64位十六进制整数初始化double的位模式,就像编译器在asm中使用的那样

kxkpmulp  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(101)

我有一个小的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

3zwjbxry

3zwjbxry1#

0xbe000000001c5f68与整数文字13690942867208167272相同,因此您的unknown1被初始化为该值(它与-4e10相差甚远,大约是1e19)。
你在程序集中看到的是,-4.656612875e-10有一个与0xbe000000001c5f68BE 00 00 00 00 1C 5F 68)相同的8个字节的对象表示。你可以转换类型,同时保留std::bit_cast的对象表示来重新解释这些位:

double unknown1 = std::bit_cast<double>(0xbe000000001c5f68u);

字符串
一般来说,这被称为“类型双关”:保持对象表示不变。正常的转换和强制转换保持表示的值相同,或尽可能接近(例如,将双精度型截断为整数,或将大整数舍入为最接近的可表示双精度型)。
在没有C++20的情况下,使用
memcpy(&foo_double, &foo_u64, sizeof(foo_double));
还有十六进制浮点文字,看起来像这样:

double unknown2 = -0x1.00000001c5f68p-31;


但是它并不与对象表示形式一一匹配。你可以看到尾数字段是十六进制的,但是binary64的前12位(符号和指数字段)是(e + 1023) | (negative ? 0x800 : 0)。对于这个数字,(-31 + 1023) | 0x800 == 0xbe0,前3个十六进制数字。

相关问题