assembly - 如何在 SSE 寄存器末尾添加 "remove"字节?

标签 assembly x86-64 sse att

对于 uni 赋值,我需要编写一个函数来计算汇编中字符串(由指针和索引定义)中的空格数。为此需要使用 pcmpeqb(即使用 SSE 寄存器),并提示使用 popcntpmovmskb。我的基本方法是以 16 字节 block 的形式处理字符串,将每个 block 加载到 %xmm8 中,并将其与初始化为包含 16 个空格的 %xmm9 进行比较。但是,我需要以某种方式专门处理最后一个 block 。

我的第一个想法是使用旋转指令来删除字符串末尾之后的垃圾。 (该字符串保证在末尾后分配一些额外的空间以防止段错误,但那里的数据可能不应该用于比较。)我偶然发现了 PSRLDQ 但似乎没有接受非直接的论点。 (或者至少拒绝我扔给它的东西。)所以我的问题是:如何删除 SSE 寄存器的最后 X 个字节,而不将其一半清零,或者逐字地这样做? (据我所知,大多数可用操作都是如此。)

我的代码(模样板)当前看起来像这样 - 有问题的位位于标签 _last::

之后的末尾
    # === Arguments ===
    # %rdi - char *input
    # %rsi - size_t count
    # === Temporaries ===
    # %rdx - how many chars to process in final run
    # %rcx - how many characters were "read" already
    # %r8 - pop count of last iteration
    # %r9
    # %r11
    # === SSE Temporaries ===
    # %xmm8 - the chunk of the string being processed
    # %xmm9 - 16 spaces

    xor %rcx, %rcx
    xor %rax, %rax
    movdqu _spaces(%rip), %xmm9

_loop:
    # set %rdx to number of characters left to process
    mov %rsi, %rdx
    sub %rcx, %rdx

    # we've reached the end of the string
    cmp %rdx, %rsi
    jge _end

    movdqu (%rdi, %rcx), %xmm8 # load chunk of string to process
    add $16, %rcx

    # less than 16 characters to process
    cmp $16, %rdx
    jg _last

_compare: #compare %xmm8 with spaces and add count of spaces to %eax
    pcmpeqb %xmm9, %xmm8
    pmovmskb %xmm8, %r8d
    popcntl %r8d, %r8d
    add %r8d, %eax
    jmp _loop

_last: # last part of string, less than 16 chars
    sub $16, %rdx
    neg %rdx
    # I need to delete possible garbage after the last chars
    psrldq %edx, %xmm8 
    jmp _compare

_end:
    ret

(那里的控制流可能仍然有问题,但我稍后会处理这个问题。)

最佳答案

不必费心尝试“删除”SSE 寄存器中的额外字节。相反,在比较并执行 PMOVMSKB 后,只需屏蔽结果掩码中与额外字节相对应的位即可。这是矢量化中非常标准的方法;不要费力去获取您想要的数据,而是处理所有内容,然后清理您不需要的数据。

关于assembly - 如何在 SSE 寄存器末尾添加 "remove"字节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15734862/

相关文章:

c++ - 如何优化从半精度 float16 到单精度 float32 的转换?

c - SSE 代码运行速度提高 30%,但在使用时显示 CPU 增加超过 20%

assembly - 标签移动到register和sub是什么意思?

assembly - 为什么编译器要在从函数返回的 MIPS "j"指令之后放置一条指令?

assembly - 在 VGA 模式下写入视频内存 13h

GCC跳转表初始化代码生成movsxd并添加?

linux - 为什么 Linux/gnu 链接器选择地址 0x400000?

x86 - 如何用SSE3实现符号功能?

assembly - 如何将字节复制到xmm0寄存器中

c - 汇编代码到C代码