为什么 mulsd 不乘以 xmm* 寄存器
why mulsd does not multiply xmm* registers
正在编写计算三维空间两点间距离的函数space。 gdb 会话:
48 mulsd xmm1, xmm0
(gdb) p/f $xmm0
= {v4_float = {5.08412027, 0, 0, 0}, v2_double = {5.3576676113063418e-315, 0}, v16_int8 = {29, -79, -94, 64, 0 <repeats 12 times>}, v8_int16 = {-20195, 16546, 0, 0, 0,
0, 0, 0}, v4_int32 = {5.08412027, 0, 0, 0}, v2_int64 = {5.3576676113063418e-315, 0}, uint128 = 3.9528689422358843932327897004554155e-4942}
(gdb) p/f $xmm1
= {v4_float = {5.08412027, 0, 0, 0}, v2_double = {5.3576676113063418e-315, 0}, v16_int8 = {29, -79, -94, 64, 0 <repeats 12 times>}, v8_int16 = {-20195, 16546, 0, 0, 0,
0, 0, 0}, v4_int32 = {5.08412027, 0, 0, 0}, v2_int64 = {5.3576676113063418e-315, 0}, uint128 = 3.9528689422358843932327897004554155e-4942}
(gdb) n
49 movsd xmm0, xmm2
(gdb) p/f $xmm1
= {v4_float = {0, 0, 0, 0}, v2_double = {0, 0}, v16_int8 = {0 <repeats 16 times>}, v8_int16 = {0, 0, 0, 0, 0, 0, 0, 0}, v4_int32 = {0, 0, 0, 0}, v2_int64 = {0, 0},
uint128 = 0}
(gdb) p/f $xmm0
= {v4_float = {5.08412027, 0, 0, 0}, v2_double = {5.3576676113063418e-315, 0}, v16_int8 = {29, -79, -94, 64, 0 <repeats 12 times>}, v8_int16 = {-20195, 16546, 0, 0, 0,
0, 0, 0}, v4_int32 = {5.08412027, 0, 0, 0}, v2_int64 = {5.3576676113063418e-315, 0}, uint128 = 3.9528689422358843932327897004554155e-4942}
奇怪的是,目标寄存器中的值为零。
您对如何执行不为零的乘法有什么建议吗?
由于下溢,你得到零。对于 x<1,x^2 更接近 零。对一个数求平方会使它离 1 更远。
5.3e-315 的震级小于 sqrt(smallest denormal double)
,因此对其求平方结果为零。 (请注意,DBL_MIN
是最小的标准化正双精度数,但非正规化可以更小。)
使用随机垃圾值测试 FP 数学不是一个好主意,除非您确定您知道指令对“常规”值(如 3.14159)的作用...FP 数学已经够难了:
[Floating-point] math is hard.
You just won’t believe how vastly, hugely, mind-bogglingly hard it is. I mean, you may think it’s difficult to calculate when trains from Chicago and Los Angeles will collide, but that’s just peanuts to floating-point math.
-- Bruce Dawson's excellent series of articles on tricky FP math stuff.
使用p $xmm0.v2_double
仅打印xmm0
的双重解释。屏幕上的噪音少了很多。
此外,您应该使用 MOVAPD(或 MOVAPS)在寄存器之间进行复制。如果要与目标寄存器的上部元素合并,请仅使用 MOVSD。
正在编写计算三维空间两点间距离的函数space。 gdb 会话:
48 mulsd xmm1, xmm0
(gdb) p/f $xmm0
= {v4_float = {5.08412027, 0, 0, 0}, v2_double = {5.3576676113063418e-315, 0}, v16_int8 = {29, -79, -94, 64, 0 <repeats 12 times>}, v8_int16 = {-20195, 16546, 0, 0, 0,
0, 0, 0}, v4_int32 = {5.08412027, 0, 0, 0}, v2_int64 = {5.3576676113063418e-315, 0}, uint128 = 3.9528689422358843932327897004554155e-4942}
(gdb) p/f $xmm1
= {v4_float = {5.08412027, 0, 0, 0}, v2_double = {5.3576676113063418e-315, 0}, v16_int8 = {29, -79, -94, 64, 0 <repeats 12 times>}, v8_int16 = {-20195, 16546, 0, 0, 0,
0, 0, 0}, v4_int32 = {5.08412027, 0, 0, 0}, v2_int64 = {5.3576676113063418e-315, 0}, uint128 = 3.9528689422358843932327897004554155e-4942}
(gdb) n
49 movsd xmm0, xmm2
(gdb) p/f $xmm1
= {v4_float = {0, 0, 0, 0}, v2_double = {0, 0}, v16_int8 = {0 <repeats 16 times>}, v8_int16 = {0, 0, 0, 0, 0, 0, 0, 0}, v4_int32 = {0, 0, 0, 0}, v2_int64 = {0, 0},
uint128 = 0}
(gdb) p/f $xmm0
= {v4_float = {5.08412027, 0, 0, 0}, v2_double = {5.3576676113063418e-315, 0}, v16_int8 = {29, -79, -94, 64, 0 <repeats 12 times>}, v8_int16 = {-20195, 16546, 0, 0, 0,
0, 0, 0}, v4_int32 = {5.08412027, 0, 0, 0}, v2_int64 = {5.3576676113063418e-315, 0}, uint128 = 3.9528689422358843932327897004554155e-4942}
奇怪的是,目标寄存器中的值为零。 您对如何执行不为零的乘法有什么建议吗?
由于下溢,你得到零。对于 x<1,x^2 更接近 零。对一个数求平方会使它离 1 更远。
5.3e-315 的震级小于 sqrt(smallest denormal double)
,因此对其求平方结果为零。 (请注意,DBL_MIN
是最小的标准化正双精度数,但非正规化可以更小。)
使用随机垃圾值测试 FP 数学不是一个好主意,除非您确定您知道指令对“常规”值(如 3.14159)的作用...FP 数学已经够难了:
[Floating-point] math is hard.
You just won’t believe how vastly, hugely, mind-bogglingly hard it is. I mean, you may think it’s difficult to calculate when trains from Chicago and Los Angeles will collide, but that’s just peanuts to floating-point math.
-- Bruce Dawson's excellent series of articles on tricky FP math stuff.
使用p $xmm0.v2_double
仅打印xmm0
的双重解释。屏幕上的噪音少了很多。
此外,您应该使用 MOVAPD(或 MOVAPS)在寄存器之间进行复制。如果要与目标寄存器的上部元素合并,请仅使用 MOVSD。