【问题标题】:Add a constant value to a xmm register in x86在 x86 中向 xmm 寄存器添加一个常量值
【发布时间】:2023-12-09 15:37:02
【问题描述】:

如何将12 添加到寄存器xmm0(双精度)?

我可以这样做,但肯定有更简单的方法:

movsd xmm0, [ecx] xor eax, eax 公司 cvtsi2sd xmm1, eax 添加 xmm0, xmm1 movsd [ecx], xmm0

也可以用浮点 x87 指令来做到这一点吗?

这对我不起作用:

fld dword ptr [ecx] fld1 faddp fstp dword ptr [ecx]

【问题讨论】:

    标签: assembly x86 sse x87


    【解决方案1】:

    你可以在内存或另一个寄存器中保持一个常量:

    _1      dq      1.0
    

    addsd   xmm1,[_1]
    

    movsd   xmm0,[_1]
    addsd   xmm1,xmm0
    

    如果您使用的是 x64,则可以这样做:

    mov     rax,1.0
    movq    xmm0,rax
    addsd   xmm1,xmm0  
    

    如果类型不匹配困扰您,请使用堆栈:

    mov     rax,1.0
    push    rax
    movsd   xmm0,[rsp]
    pop     rax
    addsd   xmm1,xmm0 
    

    至于 x87 代码,doubles 是 qwords,而不是 dwords

    【讨论】:

    • movsd xmm0,[esp]movsd xmm0,[rsp]?
    • 无论如何,使用堆栈的建议都很糟糕,并且不能避免令人惊讶地使用double 常量作为mov r64, imm64 的操作数。如果你想避免这种情况,建议mov eax, 1 / cvtsi2sd xmm0, eax
    • 您也可以在 xmm 寄存器中生成 1.0,只需要 3 条指令 IIRC(以 pcmpeqw 开头以生成全一)。阿格纳雾的Optimizing Assembly
    • mov rax,1.0 与 YASM 组合,但 NASM 拒绝该语法。
    【解决方案2】:
    vpcmpeqq  xmm1,xmm1,xmm1          ; xmm1 = [ -1 | -1 | -1 | -1 ] as ints
    vmovsd    xmm0,dword ptr [ecx]    ; xmm0 = VALUE as int
    vsubsd    xmm0,xmm0,xmm1          ; xmm0 = VALUE - (-1) = VALUE + 1
    

    以上应该是

    vpcmpeqq  xmm1,xmm1,xmm1          ; xmm1 = [ -1 | -1 | -1 | -1 ] as ints
    vmovd     xmm0,dword ptr [ecx]    ; xmm0 = VALUE as int
    vpsubd    xmm0,xmm0,xmm1          ; xmm0 = VALUE - (-1) = VALUE + 1
    

    整数加 1 和

    vpcmpeqq  xmm1,xmm1,xmm1          ; xmm1 = [ -1 | -1 ] as quads
    vmovsd    xmm0,dword ptr [ecx]    ; xmm0 = VALUE as double
    vcvtdq2pd xmm1,xmm1               ; xmm1 = [ -1.0 | -1.0 ] as doubles
    vsubsd    xmm0,xmm0,xmm1          ; xmm0 = VALUE - (-1.0) = VALUE + 1.0
    

    双倍递增 1.0

    【讨论】:

    • 您能否指定这些 AVX/SIMD 指令需要哪些 CPU 扩展?
    • 这似乎行不通。您将使用位模式0xffffffffffffffff 减去双精度浮点数,这是一个 NaN,而不是 -1。
    • 您缺少 vcvtdq2pd xmm1,xmm1 int -> FP 转换以获得双倍 -1.0。或者,-1ULL 的单个左移可能会创建正确的位模式,并在顶部设置连续位。
    • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票。
    • 感谢大家指出我的错误。我纠正了它们,所以我希望现在可以了。所有指令都是 AVX。