Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly MOVQ/PINSRQ vs VMOV填充XMM(一个有效,另一个无效)_Assembly_X86 64_Nasm - Fatal编程技术网

Assembly MOVQ/PINSRQ vs VMOV填充XMM(一个有效,另一个无效)

Assembly MOVQ/PINSRQ vs VMOV填充XMM(一个有效,另一个无效),assembly,x86-64,nasm,Assembly,X86 64,Nasm,在我的学习过程中,我开始试验AVX指令,并编写了一个简单的数组乘法,只是为了让事情顺利进行,非常基本。 第一个问题是xmm0和xmm1的填充,因为nasm不接受XMMWORD作为大小(yasm接受它,但因为它不再开发,所以我宁愿不使用它),所以我必须以2 64位的步骤填充。 我发现使用MOVQ和PINSRQ可以展示适合我的解决方案。 (某种程度上)起作用的代码是: section .data array1: dd 1.0, 2.0, 3.0, 4.0 ; Declares 2 arrays

在我的学习过程中,我开始试验AVX指令,并编写了一个简单的数组乘法,只是为了让事情顺利进行,非常基本。 第一个问题是xmm0和xmm1的填充,因为nasm不接受XMMWORD作为大小(yasm接受它,但因为它不再开发,所以我宁愿不使用它),所以我必须以2 64位的步骤填充。 我发现使用MOVQ和PINSRQ可以展示适合我的解决方案。 (某种程度上)起作用的代码是:

section .data
array1: dd  1.0, 2.0, 3.0, 4.0  ; Declares 2 arrays of 16 bytes
array2: dd  2.0, 3.0, 4.0, 5.0

section .text
global _start
_start:

mov     r8, qword array1        ; Stores the address of the 1st element
mov     r9, qword array2        ; of each array in the registers
movq    xmm0, r8                ; Populates the first half of xmm0
pinsrq  xmm0, r8, 1             ; Populates the second half   
movq    xmm1, r9                ; The same for xmm1
pinsrq  xmm1, r9, 1
vmulps  xmm0, xmm1              ; Multiplies the arrays and save in xmm0

xor     ebx, ebx
mov     rax, 1
int     80h
但在我找到这个解决方案之前,我一直在尝试:

vmovlps xmm0, qword [r8]
vmovhps xmm0, qword [r8 + 8]
这些应该先填充xmm0寄存器的低位,然后填充高位,但程序在第一个vmov中崩溃。所以,你们能解释为什么这对MOV不工作,而movq/pinsrq对工作正常吗?如果在这个简单的过程中有什么可以改进的地方,请随时提出建议

==========编辑、更新========

并尝试将结果放回内存中,这样RDI指向XMM0中保存的4个32位值中的第一个,以防万一我想返回RDI,这个组合,但是输出(由C++程序打印)是垃圾,因此显然是错误的方式:

vmulps  xmm0, xmm1     ; Multiplies the arrays and save in xmm0
vmovdqa [rdi], xmm0    ; Assembles and doesn't crash, but no meaningful result

我只是想在阅读了更多的文档之后,发布一些有效的代码,而不是通过艰苦的方式:

global mul_array_float         ; mul_array_float(float &array1, float *array2)
mul_array_float:
    vmovups xmm0, [rdi]    ; populates xmm0 and xmm1 with rdi and rsi being
    vmovups xmm1, [rsi]    ; passed by the function call
    vmulps  xmm0, xmm1     ; multiply them and save result in xmm0
    vmovups [rdi], xmm0    ; return the result to rdi (being passed by reference)
    ret

如果函数以对齐方式通过阵列,则“ups”指令不会导致速度损失。感谢Peter Cordes和Jester的考虑。

nasm
在阵列对齐的情况下对
movupd
movapd
没有问题。
movq xmm0,r8
将地址放入XMM注册表<代码>vmovlps xmm0,qword[r8]加载指向qword的文件。(效率低下,具有虚假依赖项和合并uop;使用
movq
movsd
,而不是
movlps
,除非您需要SSE1兼容性。但您使用的是AVX编码。)顺便说一句,确保您了解Haswell/Icelake vs.Skylake中SSE/AVX过渡处罚,以确保如果您使用YMM寄存器,而不仅仅是AVX-128,您不会射中自己的脚。谢谢您的评论。Jester,我将用movupd/movapd进行实验(我实际上已经尝试过vmov变体,但是vmulps只作用于2个元素,所以我认为我的加载是错误的)。彼得,我会注意你所说的,因为我不需要任何SSE兼容性,只打算使用AVX。如果你们中有人想给出答案,我很乐意接受,因为我的疑问现在已经澄清了。@PeterCordes如果我可以请你们再澄清一点,MOVLP/MOVHP列在AVX指令集中。由于我使用的是xmm而不是ymm,所以您对混合SSE/AVX有何评论?
movhps
是SSE1<代码>vmovhps为AVX1。就回答这个问题而言:你所说的一切似乎都是倒退的。你说从
[r8]
插入不起作用,但插入
r8
起作用。请注意,您链接的答案是关于将立即数常量插入XMM寄存器,这就是您对64位绝对地址所做的。我想知道您是否试图在
vmulps
/
vmovdqa
的浮动上使用
printf
,但这样做也不对,而不是使用调试器。您不能
printf
a float,您需要转换为double。