比较 xmm 中的四字

Posted

技术标签:

【中文标题】比较 xmm 中的四字【英文标题】:Comparing quadwords in xmm 【发布时间】:2011-04-19 18:43:10 【问题描述】:

使用 nasm 在 x86 汇编中编程...

使用 MOVQ 指令我将 m64 放入 xmm

MOVQ xmm1, qword [mymem64]

现在我想将它与零进行比较,以便我可以使用 Jcc

如何做到这一点,必须使用什么指令? (快速查看我没有找到的手册)

PS。我更喜欢英特尔语法:P

【问题讨论】:

【参考方案1】:

如果要根据值有条件地跳转,请不要使用 SSE。为了能够设置 Jcc 所需的标志,您需要将值存储在通用寄存器中。如果您使用的是 64 位,则可以执行以下操作:

    mov     r8,[m64]
    test    r8,r8
    jnz     .out

如果您使用的是 32 位,则可以分别检查这两个部分:

    mov     eax,dword [m64]
    mov     edx,dword [m64+4]
    or      eax,edx
    jnz     .out    

【讨论】:

我同意。但是,要提供问题的答案:使用 PCMPEQQ 和 PMOVMSKB。此外,有时您可以使用 PCMP 创建的掩码将条件跳转替换为按位算术。 哎呀,PCMPEQQ 是 SSE4.1 指令,我最近的四核甚至不支持:P 谢谢,我的电脑有 SSE4.1 但我最好不要用它 :P 我也想过这个方法,但是 MOVQ 指令很有吸引力 :D 与简单的 64 位 mov 到通用寄存器相比,您为什么觉得它更有吸引力? @Jens:好吧,如果您在 PMOVMSKB 之后测试正确的位,您可以使用任何较小的 PCMPEQ。那么这只是 SSE2。【参考方案2】:

请注意,比较 xmm 寄存器中的 64 位操作数是没有意义的,您可以使用通用寄存器。

如果您需要针对操作数进行 AND 或 ANDN 测试,您可以使用 PTEST:

PTEST  XMM0, [yourmem128] ; compare
JZ     somewhere          ; jump if all bits of the logical and are zero

如果要测试两个 64 位操作数,需要使用 PCMPEQQ

PCMPEQQ  XMM0, [yourmem128] ; compare two 64 bit words
PEXTRQ   RAX, XMM0, 1       ; upper 64 bit
MOVQ     RBX, XMM0          ; lower 64 bit
OR       RAX, RBX
NEG      RAX
JZ       somewhere          ; jump if at least one word is zero

【讨论】:

好的,现在我明白了。我用x86_64这么久了,有时候忘记了还有一些32位的机器 PEXTRQ + MOVQ 比您想要的要贵得多。使用movmskpd(2 位掩码)或pmovmskb eax, xmm0(16 位掩码)/test eax,eax/jnz at_least_one_match。 test/jnz 将宏融合到一个微指令中,不像 OR 或 NEG。 另外,neg 毫无意义。 RAX 是 -10,而 -1neg 仍然非零。所以 ZF 已经被 OR 适当地设置了。 (如果你在想NOTNOT 不会设置标志。如果你想测试至少一个零,你会在你的中使用test rax, rbx,而不是 OR。你不能从 OR 结果中恢复 AND 结果。但实际上您仍然会使用 pmovmskbcmp eax, 0xffff / jne not_all_matched【参考方案3】:

如果您只测试四字(64 位),则应避免使用 SSE:

    CMP     qword [mymem64], 0
    JNZ     .out    

即使您正在测试完整的 128 位 XMM 的价值,也是如此:

    MOV     rax, qword [mymem128]
    OR      rax, qword [mymem128+8]
    JNZ     .out    

但是,如果您的 CPU 使用 SSE 4.1,并且需要测试 128 位,则使用:

    VMOVDQU xmm0, xmmword [mymem128]
    VPTEST  xmm0, xmm0
    JNZ     .out    

【讨论】:

如果寄存器中有一个全为常量(如pcmpeqd xmm0,xmm0),您可以vptest xmm0, [mem] / jnz 仍然测试内存操作数中的所有位。 (AVX 编码不需要内存操作数对齐。)uops.info 表明现代英特尔 CPU 可以将ptest 与内存操作数微融合,因此它仍然只有 2 个微指令,与pcmpeqb/pmovmskb 相同.

以上是关于比较 xmm 中的四字的主要内容,如果未能解决你的问题,请参考以下文章

如何在 xmm 寄存器中旋转压缩四字?

将四字移动到 xmm

如何将两个打包的 64 位四字加载到 128 位 xmm 寄存器中

如何将一个 XMM 128 位寄存器拆分为两个 64 位整数寄存器?

有没有办法增加 xmm 寄存器中的值?

如何将 XMM 寄存器中的数字存储到 asm 循环中的 char 数组中 -