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

vof42yt1  于 2023-04-06  发布在  其他
关注(0)|答案(2)|浏览(147)

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

kulphzqa

kulphzqa1#

但是,具体是怎么做的呢?......
是的,这是IEEE754 binary64 (aka double )位模式的整数表示。GCC总是以这种方式打印FP常量,因为它们有时是常量传播的结果,而不是出现在源代码中的FP文字。(此外,它避免了对汇编程序中FP舍入的任何依赖。)
gcc在其asm输出中总是使用decimal作为整数常量,这对人类来说非常不方便。(在Godbolt编译器资源管理器上,使用鼠标悬停工具提示可以获得任何数字的十六进制。)
Clang的asm输出更好,包括一个带有数字十进制值的注解:

.quad   -4605718748921121997    # double -5.2999999999999998

按什么顺序?

x86的float endianness与其integer endianness匹配:两者都是little-endian。(也有可能不是这种情况,但所有现代主流体系结构都对整数和浮点数使用相同的endian,无论是大的还是小的。Floating point Endianness?。还有Endianness for floating point。)

因此,当作为64-bit IEEE-754 double加载时,内存中的低32位是double的低32位。
正如@MichaelPetch在评论中解释的那样,第一个/低dword是0x33333333,第二个/高dword是0xC0153333因此整个double具有C015333333333333的位模式
对于单精度浮点数,有https://www.h-schmidt.net/FloatConverter/IEEE754.html。(它非常好,它用复选框将位分解为二进制,以及十六进制位模式和十进制小数。非常适合学习FP指数/有效数的工作原理。)
对于双精度,请参阅https://babbage.cs.qc.cuny.edu/IEEE-754.old/64bit.html。您可以输入位模式并查看十六进制值。

ajsxfq5m

ajsxfq5m2#

#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;
}

相关问题