Assembly 如何";删除“;SSE寄存器末尾的字节数?
对于uni赋值,我需要编写一个函数来计算汇编中字符串(由指针和索引定义)中的空格数。为此,需要使用Assembly 如何";删除“;SSE寄存器末尾的字节数?,assembly,x86-64,sse,att,Assembly,X86 64,Sse,Att,对于uni赋值,我需要编写一个函数来计算汇编中字符串(由指针和索引定义)中的空格数。为此,需要使用pcmpeqb(即,使用SSE寄存器),并提示使用popcnt和pmovmkb。我的基本方法是以16字节块处理字符串,将每个块加载到%xmm8中,并将其与初始化为包含16个空格的%xmm9进行比较。但是,我需要以某种方式专门处理最后一块 我的第一个想法是使用rotate指令删除字符串末尾的垃圾。(字符串保证在结束后分配一些额外的空间以防止segfaults,但是那里的数据可能不应该用于比较。)我偶然
pcmpeqb
(即,使用SSE寄存器),并提示使用popcnt
和pmovmkb
。我的基本方法是以16字节块处理字符串,将每个块加载到%xmm8
中,并将其与初始化为包含16个空格的%xmm9
进行比较。但是,我需要以某种方式专门处理最后一块
我的第一个想法是使用rotate指令删除字符串末尾的垃圾。(字符串保证在结束后分配一些额外的空间以防止segfaults,但是那里的数据可能不应该用于比较。)我偶然发现了PSRLDQ
,但它似乎不接受非立即参数。(或者至少拒绝了我的要求。)所以我的问题是:如何删除SSE寄存器的最后X字节,而不将它的一半归零,或者逐字删除?(据我所知,它们上的大多数可用操作都是这样做的。)
我的代码(模样板)目前看起来是这样的-有问题的部分是在标签\u 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寄存器中的所有16个字符,但屏蔽
pmovskb
之后的位。请注意,像您这样使用16字节加载是不安全的,因为您可能会进入无法访问的页面。不要费心尝试“删除”SSE寄存器中的额外字节。相反,在比较并执行PMOVMSKB之后,只需屏蔽结果掩码中与额外字节相对应的位。这是矢量化中非常标准的方法;不要为了只获取所需的数据而跳转,而是处理所有内容,然后清除以后不需要的位。谢谢您的警告,但分配说明,我可以依赖字符串参数中最后一个字符之后至少16个字节的可访问性。我会在睡觉后试试你的建议,似乎需要重新安排一下控制流。