Assembly SSE中前缀的组合

Assembly SSE中前缀的组合,assembly,x86,sse,machine-code,prefixes,Assembly,X86,Sse,Machine Code,Prefixes,在SSE中,前缀066h(操作数大小覆盖)0F2H(REPNE)和0F3h(REPE)是操作码的一部分 在非SSE模式下,066h在32位(或64位)和16位操作之间切换0F2h和0F3h用于字符串操作。它们可以组合在一起,以便在同一指令中使用066h和0F2h(或0F3h),因为这是有意义的。SSE指令中的行为是什么?例如,我们有(现在忽略mod/rm): 但这是什么 66 f2 0f 58 那你呢 f2 66 0f 58 更不用说有两个相互冲突的REP前缀: f2 f3 0f 58 这

在SSE中,前缀
066h
(操作数大小覆盖)
0F2H
(REPNE)和
0F3h
(REPE)是操作码的一部分

在非SSE模式下,066h在32位(或64位)和16位操作之间切换
0F2h
0F3h
用于字符串操作。它们可以组合在一起,以便在同一指令中使用
066h
0F2h
(或
0F3h
),因为这是有意义的。SSE指令中的行为是什么?例如,我们有(现在忽略mod/rm):

但这是什么

66 f2 0f 58
那你呢

f2 66 0f 58
更不用说有两个相互冲突的REP前缀:

f2 f3 0f 58

这些的规格是什么?

我不记得在大量组合随机前缀的情况下,您应该看到什么规格,所以我猜CPU行为可能是“未定义的”,可能是特定于CPU的。(很明显,有些事情在英特尔的文档中有详细说明,但很多情况下并未涉及)。一些组合可能保留供将来使用

我天真的假设通常是,额外的前缀将不会是ops,但不能保证。考虑到一些优化手册建议使用多字节
NOP
(通常为
90h
)前缀
66h
,这似乎是合理的,例如:

db 66h, 90h; 2-byte NOP
db 66h, 66h, 90h; 3-byte NOP
db 66h, 66h, 66h, 90h; 4-byte NOP
然而,我也知道,当应用于条件跳转指令时,
CS
DS
段覆盖前缀获得了新的函数作为SSE2分支提示前缀(predict branch take=
3Eh
=
DS
覆盖;predict branch not take=
2Eh
=
CS
覆盖)

不管怎样,我看了上面的例子,总是将
XMM1
设置为all
0
XMM7
设置为all
0FFh

pxor xmm1, xmm1    ; xmm1 <- 0s
pcmpeqw xmm7, xmm7 ; xmm7 <- FFs 
2) 通过添加
0F2h
前缀,未观察到
addss
的任何变化

db 66h 
addsd xmm1, xmm7 ;total sequence = 66 F2 0F 58 CF     
db 0f2h     
addss xmm1,xmm7 ;total sequence = F2 F3 0F 58 CF
3) 但是,我通过在
0F2h
前面加前缀
addpd
观察到了一个变化:

db 0f2h    
addpd xmm1, xmm7 ;total sequence = F2 66 0F 58 CF
在这种情况下,XMM1中的结果是
000000000000000ffffffffffffffffffffh
,而不是
ffffffffffffffffffffffffh

因此我的结论是,一个人不应该做出任何假设,期待“未定义”的行为。然而,如果你能在Agner fog的书中找到一些线索,我也不会感到惊讶。

英特尔SDM第二卷手册(指令集参考)将这些称为强制前缀。将它们视为操作码的一部分

但是是的,它们是前缀,可以在实际转义字节+操作码之前与其他前缀混合。事实上,REX前缀必须跟在其他前缀后面

与往常一样,使用来自同一组的多个冲突前缀进行解码时,最后一个前缀在当前Intel硬件上具有优先权。我认为英特尔手册上说,这样做会导致不可预测的行为,因此无法保证或证明未来。这不是一件有意义的事情;如果出于对齐的原因,希望填充一条指令以使其更长,我认为将同一前缀重复几次是安全的

SSE指令使用ModR/M格式,前面有0FH 前缀字节。通常,操作不会重复以提供两个 方向(即,单独加载和存储变量)

以下三个表(表B-22、B-23和B-24)显示了 SSE SIMD浮点、SIMD整数、, 以及可缓存性和内存排序指令一些 SSE指令要求将强制性前缀(66H、F2H、F3H)作为 双字节操作码。表中包含必填前缀。


而且

2.1.2操作码

主操作码的长度可以是1、2或3字节。附加的3位操作码字段有时在 ModR/M字节。可以在主操作码中定义较小的字段。这些字段定义操作方向、位移大小、寄存器编码、条件代码或符号扩展。对用户使用的字段进行编码 操作码因操作类别而异

通用指令和SIMD指令的两字节操作码格式由以下内容之一组成:

  • 一个转义操作码字节
    0FH
    作为主操作码和第二个操作码字节
  • 强制前缀(
    66H
    F2H
    F3H
    )、转义操作码字节和第二个操作码字节(与前一个相同) 子弹)
例如,CVTDQ2PD由以下序列组成:
F3 0F E6
第一个字节是强制前缀(不是 视为重复前缀)。 通用指令和SIMD指令的三字节操作码格式由以下之一组成:

  • 一个转义操作码字节0FH作为主操作码,再加上两个附加操作码字节
  • 一个强制前缀(66H、F2H或F3H)、一个转义操作码字节,再加上两个额外的操作码字节(与 上一个项目)
例如,XMM寄存器的PHADDW由以下序列组成:66 0F 38 01。第一个字节是必填前缀。


f3 0f 58 ADDSS不是ADDPD吗?显然,在最后一种情况下,
0F2h
优先于
066h
,并将指令转换为
addsd
,这就是为什么只编写了一个块。这是一个假设,是的。然而,我认为如果有人想依靠这种行为,那是个坏主意。
db 0f2h    
addpd xmm1, xmm7 ;total sequence = F2 66 0F 58 CF