AVX2實作strlen教學
AVX2取得C字串長度
Section titled “AVX2取得C字串長度”C風格的字串結尾byte是0,如果普通的方式找0就是一個個用lodsb然後 test al, al 判斷是否為0
比起這個做法我們可以用ymm一次處理32 bytes快速找0
以下將流程拆解引導,需要解答可以展開折疊的內容
首先將內容地址載入rdi,無論從參數還是定義好的
lea rdi, s每一次找32 bytes,先讓一個暫存器清零即可,以後找完再+32像是每次翻頁一樣
xor rax, rax我們要比對的是有沒有0,所以用vpxor將一個ymm暫存器清零
vpxor ymm1, ymm1, ymm1進入loop,首先用vmovdqu(如果未對齊32 bytes)載入YWORD內容到一個ymm暫存器,要記得將rdi加上第二步清零的暫存器
vmovdqu ymm0, YWORD [rdi+rax]使用vpcmpeqb比對兩個暫存器,字串和全00的,如果比對到00和00就會得到FF
vpcmpeqb ymm0, ymm0, ymm1使用vpmovmskb做成32 bits的mask
vpmovmskb edx, ymm0判斷是否為0,如果有過FF遮罩會出現1,整個數字就不會是0
test edx, edx非零的話可以跳到exit了
jnz exit在exit有一個tzcnt reg32,rm32指令取得右邊0的個數,比如10000會得到5
tzcnt edx, edx我們應該將tzcnt的結果加上每次翻頁+32的暫存器,exit的區塊就完成了
add rax, rdx回到判斷非零跳轉的下一行,假設沒跳轉只要加上32再回到loop即可
; 上一行 jnz exitadd rax, 32 jmp loop完整範例代碼
global strlen
section .textstrlen: lea rdi, s xor rax, rax vpxor ymm1, ymm1, ymm1loop: vmovdqu ymm0, YWORD [rdi+rax] vpcmpeqb ymm0, ymm0, ymm1 vpmovmskb edx, ymm0 test edx, edx jnz exit add rax, 32 jmp loopexit: tzcnt edx, edx add rax, rdx ret在glibc的strlen-avx2.S也可以看到差不多的實現方式