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
的数组,所以您仍然需要确保正确考虑字节顺序。
我正在尝试编写 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
的数组,所以您仍然需要确保正确考虑字节顺序。