出于好奇,我使用Compiler Explorer查看一些简单C ++代码的汇编输出。
考虑以下example
int main(void){
double x = -5.3;
}
组装输出
main:
push rbp
mov rbp, rsp
movsd xmm0, QWORD PTR .LC0[rip]
movsd QWORD PTR [rbp-8], xmm0
mov eax, 0
pop rbp
ret
.LC0:
.long 858993459
.long -1072352461
我想了解如何使用
.LC0:
.long 858993459
.long -1072352461
取回我的-5.3
。
我不为人知的猜测是,我需要合并两个32位整数的位模式,并将其解释为双精度浮点数的位模式。但是如何呢?我必须将模式解释为IEEE754双精度吗?以什么顺序?
答案 0 :(得分:3)
但是,究竟如何呢? ...
是的,这是IEEE754 binary64 (aka double
)位模式的整数表示。 GCC始终以这种方式打印FP常量,因为它们有时是常量传播的结果,而不是源中出现的FP文字。 (此外,它避免了对汇编程序中FP舍入的任何依赖。)
gcc在其asm输出中始终将十进制用于整数常量,这对人类来说非常不便。 ({On the Godbolt compiler explorer,使用鼠标悬停工具提示获取任意数字的十六进制。)
Clang的asm输出更好,并且包含带数字十进制值的注释:
.quad -4605718748921121997 # double -5.2999999999999998
以什么顺序?
x86的浮点字节序匹配其整数字节序:两者均为little-endian 。 (有可能不是这种情况,但是所有现代主流体系结构都对整数和浮点数使用相同的字节序,大小不限。Floating point Endianness?。还有Endianness for floating point。)
因此,当作为64-bit IEEE-754 double
加载时,内存中的低32位是double
的低32位。
正如@MichaelPetch在评论中解释的那样,第一个/低双字是0x33333333
,第二个/高双字是0xC0153333
。 因此,整个double
的位模式为C015333333333333
对于单精度浮点数,有https://www.h-schmidt.net/FloatConverter/IEEE754.html。 (这非常好,它通过复选框将位分解为二进制,以及十六进制位模式和十进制小数。非常适合了解FP指数/有效位数的工作原理。)
有关双精度的信息,请参见https://babbage.cs.qc.cuny.edu/IEEE-754.old/64bit.html。您可以放入位模式并查看十六进制值。
答案 1 :(得分:0)
#include <iostream>
typedef struct{
union{
double decimal;
struct{
int a;
int b;
}v;
};
}Double2Int_t;
int main(){
int a1=858993459;
int a2=-1072352461;
double value=-5.3;
Double2Int_t decimal;
decimal.decimal=value;
std::cout<<decimal.v.a<<" "
<<decimal.v.b<<std::endl;
Double2Int_t decimal2;
decimal2.v.a=a1;
decimal2.v.b=a2;
std::cout<<decimal2.decimal<<std::endl;
return 0;
}