最有效的代码来搜索字符串中的字符

时间:2018-03-12 10:11:58

标签: search assembly optimization string-search

让我们说我们有一串给定的字符

DataString DB 'AGIJKSZ', 0FFH ; 

找到让我们说J的最有效的程序是什么? 按时间效应,我的意思是最少的时钟滴答。

它是带有这些指令集的x86处理器:

MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, EM64T, VT-x, AES, AVX, AVX2, FMA3, TSX

我们假设字符串和搜索字符都可以更改,但只能通过编辑代码,我们总是在寻找单个字符。字符串是ASCII。字符串结尾标有FF

答案应该只是将EAX设置为找到1 /找不到0

这是我能想到的

FindChar_1 PROC
 MOV ESI, OFFSET DataString ; 
SI
 MOV AH, 'J' ; 
Check_End:
 CMP BYTE PTR [ESI], 0FFH ; 
 JE Not_Find ; 
 CMP AH, [ESI] ; 
'DataString'
 JE Got_Equal ;
 ADD ESI, 1 ; 
 JMP Check_End ;
Got_Equal:
 MOV DL, [ESI] ; 
 JMP Done
Not_Find:
 MOV EAX,0 ; 
 RET ;
Done:
 MOV EAX,1 ; 
 RET ; 
FindChar_1 ENDP

编辑:

现在我意识到我应该提到的其他东西。我使用masm32所以我可以使用的指令仅限于非常基本的指令。

1 个答案:

答案 0 :(得分:-1)

当您需要快速代码时,请避免内存访问,跳转和复杂指令。我会扫描字符串两次:一次找到结束标记,然后找到搜索到的字符:

FindChar_2 PROC
MOV ESI, OFFSET DataString
XOR EAX,EAX
XOR ECX,ECX
XOR EDX,EDX
NOT EAX ; Let AL=EndOfString marker.
NOT ECX ; Let ECX=Max.integer.
MOV EDI,ESI
CLD
REPNE SCASB ; ECX -= String size (-9 in this example).
NOT ECX ; ECX= String size (8).
MOV AL,'J' ; The searched needle.
MOV EDI,ESI ; Restore the haystack pointer.
REPNE SCASB ; The actual search. 
  ; It returns CF if not found, because the needle is below 0FFH.
CMC ; Invert the logic.
MOV EAX,EDX ; Return false.
ADC EAX,EDX ; Return true if found.
RET
FindChar_2 ENDP