C++ 内联汇编用于数据转换

Inline assembly inside C++ for data conversion

我正在尝试编写 C++ 代码以将汇编 dq 3FA999999999999Ah 转换为 C++ double。在 asm 块中输入什么?不知道怎么取出值

int main()
{
    double x;

    asm
    {
        dq  3FA999999999999Ah
        mov x,?????
    }

    std::cout<<x<<std::endl;

    return 0;
}

从评论来看,您很想在这里使用 reinterpret cast。本质上,它的作用是告诉编译器将位序列视为它被强制转换为的类型,但它不会尝试转换值。

uint64_t raw = 0x3FA999999999999A;
double x = reinterpret_cast<double&>(raw);

在此处查看实际操作:http://coliru.stacked-crooked.com/a/37aec366eabf1da7

请注意,我在这里使用了特定的 64 位整数类型,以确保所需的位表示与 64 位双精度相匹配。此外,强制转换必须为 double&,因为 C++ 规则禁止直接强制转换为 double。这是因为 reinterpret cast 处理内存而不是类型转换,有关更多详细信息,请参阅此问题:Why doesn't this reinterpret_cast compile?。此外,您需要确保此处 64 位无符号的表示与 double 的位重新解释相匹配才能正常工作。

编辑:值得注意的是,编译器警告说这违反了严格的别名规则。快速总结一下,现在有多个值指向内存中的同一个位置,如果通过其他访问方式发生更改,编译器可能无法判断更改了哪些变量。一般来说,您不想忽略这一点,我强烈建议您阅读以下关于 strict aliasing 的文章,以了解为什么这是一个问题。因此,虽然代码的意图可能不太清楚,但您可能会发现更好的解决方案是使用 memcpy 来避免别名问题:

#include <iostream>

int main()
{
    double x;
    const uint64_t raw = 0x3FA999999999999A;
    std::memcpy(&x, &raw, sizeof raw); 
    std::cout<<x<<std::endl;

    return 0;
}

在此处查看实际操作:http://coliru.stacked-crooked.com/a/5b738874e83e896a

这避免了别名问题,因为 x 现在是具有正确组成位的双精度数,但由于 memcpy 的使用,它与原始 64 位不在同一内存位置bit int 用于表示创建它所需的位模式。因为 memcpy 将变量视为 char 的数组,所以您仍然需要确保正确考虑字节顺序。