比较 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 是 -1
或 0
,而 -1
的 neg
仍然非零。所以 ZF 已经被 OR 适当地设置了。 (如果你在想NOT
,NOT
不会设置标志。如果你想测试至少一个零,你会在你的中使用test rax, rbx
,而不是 OR。你不能从 OR 结果中恢复 AND 结果。但实际上您仍然会使用 pmovmskb
和 cmp 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 中的四字的主要内容,如果未能解决你的问题,请参考以下文章
如何将两个打包的 64 位四字加载到 128 位 xmm 寄存器中