什么是x86-64的长双?

And*_*zos 8 c linux floating-point x86-64 ieee-754

有人告诉我:

在x86-64下,FP算法使用SSE完成,因此long double是64位.

但是在x86-64 ABI中它说:

    C type  | sizeof | alignment | AMD64 Architecture
long double |   16   |    16     | 80-bit extended (IEEE-754)
Run Code Online (Sandbox Code Playgroud)

见:amd64-abi.pdf

和gcc说sizeof(long double)是16并给出FLT_DBL= 1.79769e+308FLT_LDBL = 1.18973e+4932

所以我很困惑,long double64位是怎么回事?我认为这是一个80位的表示.

Mat*_*lia 10

在x86-64下,FP算法使用SSE完成,因此long double是64位.

通常发生在x86-64(保证存在SSE指令)的情况下,但程序仍然可以自由使用x87,编译器在使用时可以使用x87 long double.

您可以通过g++在Linux上编译这样的程序来确认这一点:

#include <iostream>
#include <cstdlib>
#include <ctime>

int main()
{
    std::srand(std::time(NULL));
    float f1=rand(), f2=rand();
    double d1=rand(), d2=rand();
    long double l1=rand(), l2=rand();

    std::cout<<f1*f2<<" "<<d1*d2<<" "<<l1*l2<<std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在装配输出,我找到mulsd xmm1, xmm0double产品和mulss xmm0, xmm2float产品(包括SSE指令),但fmulp st(1), st(的x87指令)的long double产品.

因此,经过验证,编译器尽可能使用SSE,但仍允许通过旧的x87指令集进行80位精度计算.


请注意,这是特定于编译器的 - 一些编译器(例如VC++)总是忽略80位精度类型,并且只是long double作为它的同义词double.

另一方面,由于x86-64 System V ABI(在Linux上采用)强制要求long double为80位,因此编译器使用该类型的所有可用精度执行计算的唯一方法是使用x87指令.


Eri*_*hil 5

AMD ABI 实际上无法强制规定 Clong double类型是什么,因为它没有这样做的管辖权/权限。每个 C 实现都可以根据 C 标准(如果 C 实现符合标准)制定自己的类型规范,并且每个 C 实现可以选择是否符合 AMD ABI。

\n\n

这意味着您不能简单地询问 \xe2\x80\x9c x86-64 上有什么?\xe2\x80\x9d 您必须询问特定 C 实现中的long double内容。long double这意味着指定特定的 C 编译器、版本和用于编译的开关。(编译器可能有一个开关,其中一个设置生成long double64 位二进制 IEEE 754 浮点对象,另一设置生成long double80 位 Intel 浮点对象。从技术上讲,编译器、版本和开关的每种不同组合是一个独特的 C 实现。)

\n\n

一个编译器实现long double为 64 位二进制 IEEE-754 浮点对象的编译器只是将它们作为 AMD ABI 调用的对象进行传递double;它从来没有像 ABI 所说的那样传递它们long double。这样做时,编译器的这一方面将仅与处理类似的其他软件兼容long double

\n

  • @StephenCanon:是的,严格来说它不是“AMD ABI”或“x86-64 ABI”,它是“System V x86-64 ABI”。Linux 选择遵守它,而 Windows 则没有。 (4认同)
  • 你的措辞有点奇怪。用户态应用程序必须与内核就类型的大小、对齐和表示达成一致——否则系统调用将无法工作。这就是 ABI 的功能。从这个意义上说,ABI“强制”应用程序遵守它,因为如果它们不这样做,它们将无法工作(至少当它们尝试进行系统调用时)。 (2认同)