Assembly 如何在XMM中将单个浮点从内存转换为四个浮点?

Assembly 如何在XMM中将单个浮点从内存转换为四个浮点?,assembly,x86,nasm,sse,Assembly,X86,Nasm,Sse,以下代码旨在将每个压缩单浮点值除以4: quarter dd 0.25 ... movups xmm1, [quarter] mulps xmm0, xmm1 但是,它不会执行所需的操作,因为来自[quarter]的数据被视为16字节实体: (gdb) p $xmm1 $2 = {v4_float = {0.25, 0.00200051093, 7.8472714e-44, 8.40779079e-45} 显而易见的解决方法是将quarter声明为四元素数组,但我很好奇,是否有某种优

以下代码旨在将每个压缩单浮点值除以4:

quarter dd 0.25
...

movups  xmm1, [quarter]
mulps   xmm0, xmm1
但是,它不会执行所需的操作,因为来自
[quarter]
的数据被视为16字节实体:

(gdb) p $xmm1
$2 = {v4_float = {0.25, 0.00200051093, 7.8472714e-44, 8.40779079e-45}
显而易见的解决方法是将
quarter
声明为四元素数组,但我很好奇,是否有某种优先方法可以传输或复制第一个元素?例如:

movss   xmm1, [quarter]
; some magic kung-fu
mulps   xmm0, xmm1
编辑:

由于下面的评论,我最终得到了
shufps

movss   xmm1, [quarter]
shufps  xmm1, xmm1, 0     ; broadcast the least significant element
mulps   xmm0, xmm1

看看nasm中的指令
vbroadcastss xmm,m32
,我通常只说
乘以4 dd 0.25
。它使数据部分变大,但只保存一条指令。即使使用AVX,
movups
与广播保存1周期相比,我相信。当然,这取决于您是否在优化速度或代码大小。就我而言,这根本没有什么明显的区别,我喜欢它的便利性。@YanZhou在什么方面
movd
比正确的
movss
更可取?在某些CPU上,这可能很重要。@fuz:没错
movd
是一个整数域加载,因此在某些CPU(Nehalem)上,作为FP乘法或洗牌的输入,它有额外的延迟。但是,数据类型对于任何已知CPU上的存储都不重要,因此一些编译器可以并且确实使用
movups
/
movaps
来存储一个字节的代码,而不是
movdqa
来加载。(但大多数编译器仍然使用
movapd
而不是
movaps
,即使没有现有的硬件关心这一点)。此外,是的,load+shufps是编译器实现
的方式。不过,大多数编译器选择扩展常量,以便直接从内存中使用。(16B已对齐并已广播)。如果您只是在循环之前做一次,那么用广播加载、PMOVZX和类似的东西保持常量的紧凑性可能是值得的(特别是如果您的常量不能全部放在单个缓存线中)。或者,如果它们很简单,甚至可以动态生成位模式;请参阅Agner Fog的优化装配指南,以及