UNI端口分配,我需要編寫用於計數在一個字符串中組件(由指針和索引定義)的空格數的函數。有使用pcmpeqb
這個要求(即與SSE寄存器的工作),以及提示使用popcnt
和pmovmskb
。我的基本方法是,在處理16字節的塊串,每塊裝入%xmm8
並與%xmm9
被初始化爲包含16個空格比較。但是,我需要特意處理最後一個塊。如何在SSE寄存器末尾「刪除」字節?
我首先想到的是使用一個循環指令來刪除垃圾過去的字符串的結尾。 (該字符串保證有結束後分配一些額外的空間,以防止段錯誤,但該數據可能不應該被用於比較。)我偶然發現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
(那裏的控制流可能仍然有問題,但我會在稍後處理。)
感謝您的警告,但分配狀態表明,我可以依賴至少16字節可以在字符串參數中的最後一個字符後訪問。我在睡覺之後嘗試一下你的建議,似乎需要重新安排一下控制流程。 – millimoose