For the SharpBASIC compiler I've written a function called instr (in-string) with inline asm to find a substring from a specific start position. The function works, but I'm learning ASM as I go, so I wonder if the code is ok or if it could be optimized/shortened. Elsewhere I read that repe cmpsb isn't the fastest way to compare strings. Any suggestions are very welcome.
func _sb_instr(src: str, sbs: str, start: int): int
dim srcl, sbsl: int; ' source and sub-string length
do
asm do
push edi
push esi
mov eax, [ebp + 16] ; source string descriptor
call _sb_load_strdesc ; address in ebx, length in edx
mov esi, ebx ; string address in esi
test edx, edx ; non-zero is fixed-length
jnz .next1
call _sb_strzlen ; null-terminated string
.next1:
test edx, edx ; anything to search in?
jz .out
mov [ebp - 8], edx ; save source string length
mov eax, [ebp + 12] ; sub-string descriptor
call _sb_load_strdesc ; address in ebx, length in edx
test edx, edx ; non-zero is fixed-length
jnz .next2
call _sb_strzlen ; null-terminated string
.next2:
test edx, edx ; anything to search for?
jz .out
mov [ebp - 12], edx ; save sub-string length
mov ecx, [ebp + 8] ; start position
mov edx, [ebp - 8] ; source string length
sub edx, ecx ; length minus start position
mov eax, edx ; save length
sub eax, [ebp - 12] ; subtract sub-string length
cmp eax, 0
jl .out ; sub-string is longer
dec ecx ; 0-based
push esi ; save start address
add esi, ecx ; start address from start position
.repeat: ; compare loop
mov ecx, [ebp - 12] ; substring length is loop counter
mov edi, ebx ; sub-string address in edi
cld
mov eax, esi ; save esi
repe cmpsb ; compare strings (edi with esi)
jz .done
inc eax ; move up one byte
mov esi, eax ; restore modified esi
dec edx ; decrement source string length
and edx, edx ; non-zero means continue search
jnz .repeat
jmp .out
.done:
sub esi, [ebp-12] ; beginning of sub-string
pop eax ; restore start address
sub esi, eax ; start position in string
inc esi ; position 1-based
mov [ebp - 4], esi ; save result
.out:
pop esi
pop edi
end;
end;