int32_t 和 int16_t 之间的 sse4 压缩和(符号扩展至 int32_t)

Fer*_*Mom 1 linux sse x86-64 intel

我有以下代码片段(可以在此处找到要点),其中我尝试对 4 个 int32_t 负值和 4 个 int16_t 值(将符号扩展为 int32_t)之间进行求和。

    extern  exit

    global _start

    section .data

a:     dd -76, -84, -84, -132
b:     dw 406, 406, 406, 406
    
    section .text
_start:
    movdqa xmm0, [a]
    pmovsxwd xmm2, [b]
    paddq xmm0, xmm2
    ;Expected: 330, 322, 322, 274
    ;Results:  330, 323, 322, 275
    call exit
Run Code Online (Sandbox Code Playgroud)

然而,当通过我的调试器时,我无法理解为什么输出结果与预期结果不同。任何想法 ?

Pet*_*des 5

paddq执行 64 位 qword 块,因此会跨越两个 32 位边界进位,导致每个 qword 的高半部分偏移 1。

paddd是 32 位双字块,与pmovsxwd双字元素目标大小匹配。这是一个 SIMD 操作,具有 4 个独立的加法,彼此独立。


顺便说一句,您可以通过将 16 字节对齐加载折叠到 的内存操作数中来提高效率padd,但是对于调试来说,它可以帮助通过单独的加载查看寄存器中的两个输入。

  default rel           ; use RIP-relative addressing modes when possible

_start:
   movsxwd xmm0, [b]
   paddd   xmm0, [a]
Run Code Online (Sandbox Code Playgroud)

另外,您通常会将只读数组放入section .rodata.