Agber Fog's Strlen algo in PowerBASIC.

Started by hutch--, December 20, 2009, 08:03:40 PM

Previous topic - Next topic

hutch--

If you know your way around PowerBASIC you don't need this type of function all that often as the length of a string is stored 4 bytes below its start address but where you do, this is still an excellent very fast function. It comes with a duplicate guard. If you need the length of a basic dynamic string without scanning it, there is an algo below that will do it for you.


' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    #IF NOT %DEF(%fn_StrLen)
    %fn_StrLen = 1

' --------------------------------------------------------------------------------------------------

FUNCTION StrLen(ByVal item as DWORD) as DWORD

    #REGISTER NONE

    ! mov     eax, item               ' get pointer to string
    ! lea     edx, [eax+3]            ' pointer+3 used in the end
    ! mov     ebx, &H80808080

  lbl0:
  ' --------------------
  ' manually unroll by 3
  ' --------------------
    ! mov     edi, [eax]              ' read first 4 bytes
    ! add     eax, 4                  ' increment pointer
    ! lea     ecx, [edi-&H01010101]   ' subtract 1 from each byte
    ! not     edi                     ' invert all bytes
    ! and     ecx, edi                ' and these two
    ! and     ecx, ebx
    ! jnz     nxt

    ! mov     edi, [eax]              ' read first 4 bytes
    ! add     eax, 4                  ' increment pointer
    ! lea     ecx, [edi-&H01010101]   ' subtract 1 from each byte
    ! not     edi                     ' invert all bytes
    ! and     ecx, edi                ' and these two
    ! and     ecx, ebx
    ! jnz     nxt

    ! mov     edi, [eax]              ' read first 4 bytes
    ! add     eax, 4                  ' increment pointer
    ! lea     ecx, [edi-&H01010101]   ' subtract 1 from each byte
    ! not     edi                     ' invert all bytes
    ! and     ecx, edi                ' and these two
    ! and     ecx, ebx
    ! jnz     nxt
  ' --------------------
    ! mov     edi, [eax]              ' read first 4 bytes
    ! add     eax, 4                  ' 4 increment DWORD pointer
    ! lea     ecx, [edi-&H01010101]   ' subtract 1 from each byte
    ! not     edi                     ' invert all bytes
    ! and     ecx, edi                ' and these two
    ! and     ecx, ebx
    ! jz      lbl0                    ' no zero bytes, continue loop

  nxt:
    ! test    ecx, &H00008080         ' test first two bytes
    ! jnz     lbl1
    ! shr     ecx, 16                 ' not in the first 2 bytes
    ! add     eax, 2
  lbl1:
    ! shl     cl, 1                   ' use carry flag to avoid branch
    ! sbb     eax, edx                ' compute length

    ! mov FUNCTION, eax

END FUNCTION

' --------------------------------------------------------------------------------------------------

    #ENDIF

' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤


Get dynamic string length without scanning it.


' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

FUNCTION lnbstr(bstr$) as DWORD

  ' ----------------------------
  ' get the stored string length
  ' ----------------------------

    #REGISTER NONE

    LOCAL pstr as DWORD

    pstr = StrPtr(bstr$)        ' get the string address
    ! mov eax, pstr
    ! mov eax, [eax-4]          ' get the stored buffer length
    ! mov FUNCTION, eax         ' return it in EAX

End FUNCTION

' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php