Sign in to follow this  
Followers 0
Iczer

Inline ASM unicode-friendly string replacing function

1 post in this topic

Maybe someone have fast unicode-friendly string replacing function written in Assembler for work with UTF-8 encoded text in 32/64 bit scripts (FreeBasic)

I'm ported this function to x64 by replacing exx registers names to rxx, but it work only fo ascii letters - UTF8 wont work. And currently i do not want resort to UTF-16...

#ifdef __FB_64BIT__

        Function StringReplaceASCII(TiStr As String ,TiFind As String ,TiRep As String ) As String  '/' this function only 64bit
            Dim As ZString Ptr iStr,iFind, iRep
            Dim As Integer  icor= 0
            Dim As Integer i, code
        
            If TiStr="" Or TiFind="" Then
                Function = TiStr
                Exit Function
            EndIf
            If TiRep="" Then
                TiRep="?"
                icor=1
            EndIf
            iStr=StrPtr(TiStr)
            iFind= StrPtr(TiFind)
            iRep= StrPtr(TiRep)
        
            Dim As Integer iSize=Len(TiStr)-Len(TiFind)
            Dim As ZString Ptr dStr=CAllocate(Len(TiStr)*20)
            Dim  As String s
        
             Asm
                mov rsi,[iStr]
                add [iSize],rsi
                mov rbx,[iFind]
                inc dword Ptr[iSize]
                mov rdi,[dStr]
             End Asm
             Asm Sub rsi,1
             Asm
                jmp Start1
        Start2: add rsi,rcx
        Start1: add rsi,1
                cmp [iSize],rsi
                jle Done
                movzx rax,Byte Ptr[rsi]
                cmp al,[rbx]
                je Match
                mov [rdi],al
                add rdi,1
                jmp Start1
        Match:  mov rcx,-1
                mov rdx,rbx
        B1:     add rcx,1
                movzx rax,Byte Ptr[rdx]
                Test rax,rax
                jz Change
                add rdx,1
                cmp [rsi+rcx],al
                je B1
                movzx rax,Byte Ptr[rsi]
                mov [rdi],al
                add rdi,1
                jmp Start1
        Change: mov rdx,[iRep]
             End Asm
        saute:  Asm Sub rcx,1
             Asm
        B2:     movzx rax,Byte Ptr[rdx]
                Test rax,rax
                jz Start2
                add rdx,1
                mov [rdi],al
                add rdi,1
                jmp B2
        Done:   mov rcx,-1
        B3:     add rcx,1
                movzx rax,Byte Ptr[rsi+rcx]
                mov [rdi+rcx],al
                Test rax,rax
                jnz B3
               ' mov rax,[dStr]
               ' mov [toto],rax
            End Asm
            s=*dStr
            If icor=0 Then
                Function = s
                Deallocate dStr
                Exit Function
            EndIf
        
            code=Asc("?") ' change it here if you want
            asm
                mov rsi, [dStr]
                mov rdx, -1       '' "get" pointer
                Xor rcx, rcx      '' "put" pointer
                Test rsi, rsi     '' in case passed null string
                jz  1f
              0:
                inc rdx
                movzx rax, Byte Ptr [rsi+rdx]
                Test rax, rax
                jz  1f
                cmp rax,[code]  '
                je  0b
                mov [rsi+rcx], al
                inc rcx
                jmp 0b
              1:
                mov [i], rcx
            End asm
                s=Left$(*dStr,i)
            Function = s
            Deallocate dStr
        End Function

#Else

        Function StringReplaceASCII(TiStr As String ,TiFind As String ,TiRep As String ) As String  '/' this function only 32bit
            Dim As ZString Ptr iStr,iFind, iRep
            Dim As Integer  icor= 0
            Dim As Integer i, code
        
            If TiStr="" Or TiFind="" Then
                Function = TiStr
                Exit Function
            EndIf
            If TiRep="" Then
                TiRep="?"
                icor=1
            EndIf
            iStr=StrPtr(TiStr)
            iFind= StrPtr(TiFind)
            iRep= StrPtr(TiRep)
        
            Dim As Integer iSize=Len(TiStr)-Len(TiFind)
            Dim As ZString Ptr dStr=CAllocate(Len(TiStr)*20)
            Dim  As String s
        
             Asm
                mov esi,[iStr]
                add [iSize],esi
                mov ebx,[iFind]
                inc dword Ptr[iSize]
                mov edi,[dStr]
             End Asm
             Asm Sub esi,1
             Asm
                jmp Start1
        Start2: add esi,ecx
        Start1: add esi,1
                cmp [iSize],esi
                jle Done
                movzx eax,Byte Ptr[esi]
                cmp al,[ebx]
                je Match
                mov [edi],al
                add edi,1
                jmp Start1
        Match:  mov ecx,-1
                mov edx,ebx
        B1:     add ecx,1
                movzx eax,Byte Ptr[edx]
                Test eax,eax
                jz Change
                add edx,1
                cmp [esi+ecx],al
                je B1
                movzx eax,Byte Ptr[esi]
                mov [edi],al
                add edi,1
                jmp Start1
        Change: mov edx,[iRep]
             End Asm
        saute:  Asm Sub ecx,1
             Asm
        B2:     movzx eax,Byte Ptr[edx]
                Test eax,eax
                jz Start2
                add edx,1
                mov [edi],al
                add edi,1
                jmp B2
        Done:   mov ecx,-1
        B3:     add ecx,1
                movzx eax,Byte Ptr[esi+ecx]
                mov [edi+ecx],al
                Test eax,eax
                jnz B3
               ' mov eax,[dStr]
               ' mov [toto],eax
            End Asm
            s=*dStr
            If icor=0 Then
                Function = s
                Deallocate dStr
                Exit Function
            EndIf
        
            code=Asc("?") ' change it here if you want
            asm
                mov esi, [dStr]
                mov edx, -1       '' "get" pointer
                Xor ecx, ecx      '' "put" pointer
                Test esi, esi     '' in case passed null string
                jz  1f
              0:
                inc edx
                movzx eax, Byte Ptr [esi+edx]
                Test eax, eax
                jz  1f
                cmp eax,[code]  '
                je  0b
                mov [esi+ecx], al
                inc ecx
                jmp 0b
              1:
                mov [i], ecx
            End asm
                s=Left$(*dStr,i)
            Function = s
            Deallocate dStr
        End Function

#EndIf

or pretty same:

#ifdef __FB_64BIT__

    Function StringReplaceUnicode(iStr As ZString Ptr,iFind As ZString Ptr,iRep as ZString Ptr) As ZString Ptr
        Dim as integer iSize=Len(*iStr)-Len(*iFind)
            Asm
            mov rsi,[iStr]
            add [iSize],rsi
            mov rbx,[iFind]
            inc dword ptr[iSize]
            mov rdi,[dStr]
            sub rsi,1
            jmp _Start1
    _Start2: add rsi,rcx
    _Start1: add rsi,1
            cmp [iSize],rsi
            jle _Done
            movzx rax,BYTE PTR[rsi]
            cmp al,[rbx]
            je _Match
            mov [rdi],al
            add rdi,1
            jmp _Start1
    _Match:  mov rcx,-1
            mov rdx,rbx
    _B1:     add rcx,1
            movzx rax,BYTE PTR[rdx]
            test rax,rax
            jz _Change
            add rdx,1
            cmp [rsi+rcx],al
            je _B1
            movzx rax,BYTE PTR[rsi]
            mov [rdi],al
            add rdi,1
            jmp _Start1
    _Change: mov rdx,[iRep]
            sub rcx,1
    _B2:     movzx rax,BYTE PTR[rdx]
            test rax,rax
            jz _Start2
            add rdx,1
            mov [rdi],al
            add rdi,1
            jmp _B2
    _Done:   mov rcx,-1
    _B3:     add rcx,1
            movzx rax,BYTE PTR[rsi+rcx]
            mov [rdi+rcx],al
            test rax,rax
            jnz _B3
            mov rax,[dStr]
            mov [Function],rax
        End Asm
    End Function


#Else

    Function StringReplaceUnicode(iStr As ZString Ptr,iFind As ZString Ptr,iRep as ZString Ptr) As ZString Ptr
        Dim as integer iSize=Len(*iStr)-Len(*iFind)
            Asm
            mov esi,[iStr]
            add [iSize],esi
            mov ebx,[iFind]
            inc dword ptr[iSize]
            mov edi,[dStr]
            sub esi,1
            jmp _Start1
    _Start2: add esi,ecx
    _Start1: add esi,1
            cmp [iSize],esi
            jle _Done
            movzx eax,BYTE PTR[esi]
            cmp al,[ebx]
            je _Match
            mov [edi],al
            add edi,1
            jmp _Start1
    _Match:  mov ecx,-1
            mov edx,ebx
    _B1:     add ecx,1
            movzx eax,BYTE PTR[edx]
            test eax,eax
            jz _Change
            add edx,1
            cmp [esi+ecx],al
            je _B1
            movzx eax,BYTE PTR[esi]
            mov [edi],al
            add edi,1
            jmp _Start1
    _Change: mov edx,[iRep]
            sub ecx,1
    _B2:     movzx eax,BYTE PTR[edx]
            test eax,eax
            jz _Start2
            add edx,1
            mov [edi],al
            add edi,1
            jmp _B2
    _Done:   mov ecx,-1
    _B3:     add ecx,1
            movzx eax,BYTE PTR[esi+ecx]
            mov [edi+ecx],al
            test eax,eax
            jnz _B3
            mov eax,[dStr]
            mov [Function],eax
        End Asm
    End Function

#EndIf

 

Also - speed wise - maybe just go with AutoItX.dll x86/x64 ?

Share this post


Link to post
Share on other sites



Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0