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, 32jmp 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也可以看到差不多的实现方式