假设内存中有一个 long double 变量。根据我在网上找到的信息,它有 12 字节大。如果寄存器大小是64位,CPU如何对其进行操作?是否以某种方式划分?
事实并非如此。 x87 硬件格式的长度为 80 位(10 字节),即传统 x87 FPU 寄存器的宽度(仍然存在,如果您不想使用 Kahan 求和或 double-double 之类的东西,则对于更宽的精度很有用) 技巧。
double
和 float
通常在使用 SSE2 指令的 XMM 寄存器的低位元素中完成,除了为兼容而编译的 32 位代码中) 2000 年代初期或更早的 CPU。)sizeof(long double)
中额外的2个字节被填充以使sizeof(long double)
成为i386 System V ABI(32位代码)中alignof(long double) == 4
的倍数。
在 x86-64 System V ABI 中,
sizeof
和 alignof(long double)
增加到 16,因此它无法跨缓存行拆分。这是 6 个字节的填充,仍然是由 fld m80
和 fstp m80
指令访问的 10 个字节的实际数据(比正常的 dword 或 qword float 或 double 加载和存储慢几倍,请参阅我在逆计算问答中的回答)。
80 位
long double
永远不会加载到 128 位 XMM 寄存器(除非复制它),或加载到 64 位整数寄存器(除非复制它,或者使用尾数和指数字段执行整数操作,就像实现时一样log
或 exp
。)x87 寄存器中只有用于对其进行数学计算的硬件指令。
请注意,x86 和 x64 的 MSVC 使用 64 位
long double
,格式与 double
相同。 GCC 可以选择与 ABI 兼容,或者让 long double
成为 80 位 x87 类型,以方便地实现更高精度的 FP。但在 Windows 上请注意 32 位库,它们将 x87 FPU 精度位设置为四舍五入到更少的位(这会在一定程度上加快 div 和 sqrt 的速度)。请参阅https://randomascii.wordpress.com/2012/03/21/intermediate-floating-point- precision/回复:DirectX 库正在执行此操作。