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

Assembly 有没有办法增加xmm寄存器中的值?,assembly,x86,add,sse,Assembly,X86,Add,Sse,我想知道,有没有办法增加xmm寄存器中的值,或者只能将值移到一个寄存器中 我的意思是,你可以这样做: inc eax 或者像这样: inc [ebp+7F00F000] 有没有一种方法可以对xmm执行同样的操作 我试过类似的东西,但是。。。它不起作用 inc [rbx+08] movss xmm1,[rbx+08] 我甚至尝试过一些非常愚蠢的事情,但也没有成功 push edx pextrw edx,xmm2,0 add edx,1 mov [rbx+08],edx movss x

我想知道,有没有办法增加xmm寄存器中的值,或者只能将值移到一个寄存器中

我的意思是,你可以这样做:

inc eax
或者像这样:

inc [ebp+7F00F000]
有没有一种方法可以对xmm执行同样的操作

我试过类似的东西,但是。。。它不起作用

  inc [rbx+08]
  movss xmm1,[rbx+08]
我甚至尝试过一些非常愚蠢的事情,但也没有成功

push edx
pextrw edx,xmm2,0
add edx,1
mov [rbx+08],edx
movss xmm1,[rbx+08]
pop edx

简言之,不,不是你想的那样

在SSE下,所有原始XMM寄存器都是浮点寄存器。浮点没有增量操作

SSE2添加了许多整数类型寄存器,但仍然没有增量。这些寄存器和加法运算实际上是用于高速算术运算,包括点积、带舍入的精确积等

增量操作是应用于通用寄存器或累加器的操作


您可能会在一般概述和函数方面发现一些有用的信息。

对于xmm regs没有等价的
inc
,也没有立即操作数形式的
paddw
(因此也没有等价的
addeax,1

仅适用于xmm/m128源操作数。所以如果你想增加向量的一个元素,你需要从内存中加载一个常量

e、 g.增加xmm0所有元素的最便宜方法是:

; outside the loop
pcmpeqw    xmm1,xmm1     # xmm1 = all-ones = -1

; inside the loop
psubw      xmm0, xmm1    ; xmm0 -= -1   (in each element).  i.e. xmm0++

如果构造常数需要两条以上的指令,或者寄存器压力是一个问题,那么从内存加载常数可能是一个好主意


例如,如果要构造一个仅递增低32位元素的常数,可以使用字节移位将其他元素归零:

; hoisted out of the loop
pcmpeqw    xmm1,xmm1     # xmm1 = all-ones = -1
psrldq     xmm1, 12      # xmm1 = [ 0 0 0 -1 ]


; in the loop
psubd      xmm0, xmm1

如果您的尝试应该只增加xmm2中的低16位元素,那么是的,这是一个愚蠢的尝试。IDK将要执行的操作存储到
[rbx+8]
中,然后加载到xmm1(将高96位归零)

下面是如何以一种不那么愚蠢的方式编写xmm->gp->xmm往返。(与带有向量常数的
paddw
相比仍然很糟糕)

如果您想使用16位以外的元素,您可以使用SSE4.1
pinsrb
/
d
/
q
,或者使用
movd
和shuffles



有关如何使用SSE向量的更多好提示,请参见指南。还有标记wiki中的其他链接。

您想增加xmm寄存器中的所有整数值,还是只增加一个整数值?可能重复@HansPassant:这是关于浮点的问题。这个似乎不是,因为它使用整数
inc
pextrw
。否则OP就真的很混乱了。如果它应该是关于浮点的,那么很明显,你只需要添加一个向量,除了一个之外,所有元素都有零。(如果是低位元素,则使用
addss
,因为这些insn与旧值合并)。SSE2使用相同的XMM寄存器,它只是添加了对整数数据类型进行操作的指令,包括对b/w/d/q元素大小的整数加减。在XMM regs中进行向量整数加法是完全正常的。彼得,现代AMD/Intel上的SSE2在int和fp块分开时是否对int和fp使用相同的XMM寄存器,并且在AMD中它们有单独的PRF:@osgx:之前没有看到你的答复,因为你没有@-通知我。我的意思是相同的架构寄存器。Intel和AMD CPU对vector int和vector fp有单独的转发网络。不过,英特尔SnB家族肯定是如此。由于大多数代码不会同时使用这两种方法,因此对于相同的硅区域,这会提供更多的无序执行能力。我认为Bobcat实际上是一样的:“int”块是标量整数(通用)寄存器。注意IntMul单位:FP在这里仅表示XMM/MMX/x87。
; hoisted out of the loop
pcmpeqw    xmm1,xmm1     # xmm1 = all-ones = -1
psrldq     xmm1, 12      # xmm1 = [ 0 0 0 -1 ]


; in the loop
psubd      xmm0, xmm1
# don't push/pop.  Instead, pick a register you can clobber without saving/restoring
movd    edx, xmm2       # this is the cheapest way to get the low 16.  It doesn't matter that we also get the element 1 as garbage in the high half of edx
inc     edx             # we only care about dx, but this is still the most efficient instruction
pinsrw  xmm2, edx, 0    # normally you'd just use movd again, but we actually want to merge with the old contents.