了解程序集列表输出中的GCC浮点常量

时间:2018-08-16 18:34:25

标签: gcc assembly floating-point x86-64

出于好奇,我使用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双精度吗?以什么顺序?

2 个答案:

答案 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;
}