首页 > 解决方案 > 了解汇编列表输出中的 GCC 浮点常量

问题描述

出于好奇,我正在使用Compiler Explorer查看一些简单 C++ 代码的汇编输出。

考虑以下示例

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 双精度吗?以什么顺序?

标签: gccassemblyfloating-pointx86-64

解决方案


但是,究竟如何?...

是的,这是IEEE754 binary64 (aka double)位模式的整数表示。GCC 总是以这种方式打印 FP 常量,因为它们有时是常量传播的结果,而不是出现在源代码中的 FP 文字。(它还避免了对汇编器中 FP 舍入的任何依赖。)

gcc 在其 asm 输出中始终使用十进制表示整数常量,这对人类来说非常不方便。(在 Godbolt 编译器资源管理器上,使用鼠标悬停工具提示获取任意数字的十六进制。)

Clang 的 asm 输出更好,并且包含带有数字十进制值的注释:

    .quad   -4605718748921121997    # double -5.2999999999999998

以什么顺序?

x86 的浮点字节序匹配它的整数字节序:两者都是 little-endian。(情况可能并非如此,但所有现代主流架构都对整数和浮点数使用相同的字节序,无论大小。 浮点字节序?浮点字节序。)

因此,当作为64 位 IEEE-754double加载时,内存中的低 32 位是double.

正如@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。您可以输入位模式并查看十六进制值。


推荐阅读