Announcement

Collapse
No announcement yet.

ASM Array copy & szString functions

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • ASM Array copy & szString functions

    One of the advantages of PowerBASIC is its flexibility in programming
    style. PowerBASIC has a very powerful set of string manipulation functions
    but the operating system still mainly uses zero terminated strings so in
    some instances, it is more economical to work in zero terminated strings.

    In other instances, some people who are more familiar with this format
    still like to work this way and of course, sometimes there is an advantage
    in using this format.

    Below is a test application that has a set of zero terminated string
    functions written in assembler. The are not as easy to use as the basic
    dynamic strings but they are useful in many instances. Where possible,
    they have used DWORD size instructions to get the speed up to an
    acceptable level.

    Zero terminated strings have the disadvantage that they must be scanned to
    get their length so an algorithm written by Agner Fog has been used
    because of its speed advantage over classic byte scanners.

    There is also an example of how to copy a numeric array using a DWORD
    memory copy routine written in assembler. Rather than some messy looped
    assignment process, this routine uses the direct address of the first
    member of each array and copies the correct number of bytes from the
    source address to the destination address.

    For having written two other test pieces, one using 4 32 bit registers and
    the second using 4 64 bit MMX registers, the "rep movsd" method has not
    been improved on so the memory copy routine is in the smart end of the
    market in terms of speed.

    Note that you cannot use this technique on a dynamic string array as they
    are not stored sequentially in memory.

    A small piece of pure PowerBASIC for your pleasure.

    Regards,

    [email protected]

    Code:
      ' #########################################################################
      
      #COMPILE EXE
      
      ' ----------------------------
      ' Function / Sub declarations
      ' ----------------------------
      
      DECLARE FUNCTION MessageBox LIB "user32.dll" ALIAS "MessageBoxA" _
                      (ByVal DWORD,ByVal DWORD,ByVal DWORD,ByVal DWORD) as LONG
      
      DECLARE FUNCTION szLen(ByVal lpszString as LONG) as LONG
      
      DECLARE SUB MemCopyD(ByVal src as LONG, _
                           ByVal dst as LONG, _
                           ByVal ln  as LONG)
      
      DECLARE SUB szCatStr(ByVal lpszSource as LONG, _
                           ByVal lpszAdd    as LONG)
      
      DECLARE SUB szLeft(ByVal lpszSource  as LONG, _
                         ByVal lpszTarget  as LONG, _
                         ByVal ln as LONG)
      
      DECLARE SUB szMid(ByVal lpszSource   as LONG, _
                        ByVal lpszTarget   as LONG, _
                        ByVal stPos        as LONG, _
                        ByVal ln           as LONG)
      
      DECLARE SUB szRight(ByVal lpszSource as LONG, _
                          ByVal lpszTarget  as LONG, _
                          ByVal ln as LONG)
      
      DECLARE SUB szRevStr(ByVal lpszSource as LONG,ByVal lpszTarget as LONG)
      
      ' #########################################################################
      
      FUNCTION WinMain(ByVal Instance      as LONG, _
                       ByVal hPrevInstance as LONG, _
                       lpszCmdLine         as ASCIIZ PTR, _
                       ByVal nCmdShow      as LONG) AS LONG
      
          LOCAL lpAr1      as LONG
          LOCAL lpAr2      as LONG
      
          LOCAL szText     as ASCIIZ * 64
          LOCAL szAdd      as ASCIIZ * 20
          LOCAL sztTl      as ASCIIZ * 16
          LOCAL szBuffer   as ASCIIZ * 64
          LOCAL szMidStr   as ASCIIZ * 8
          LOCAL szRightStr as ASCIIZ * 8
          LOCAL szExtra    as ASCIIZ * 128
      
          szText = "Hi there folks ! "
          szAdd  = "Message Box Test"
          sztTl  = "Message Box"
      
        ' --------------------
        ' sz string functions
        ' --------------------
          szLeft VarPtr(szAdd),VarPtr(szBuffer),11
          szCatStr VarPtr(szText),VarPtr(szBuffer)
      
          szMid VarPtr(szText),VarPtr(szMidStr),8,6
          szCatStr VarPtr(szText),VarPtr(szMidStr)
      
          szRight VarPtr(szAdd),VarPtr(szRightStr),5
          szCatStr VarPtr(szText),VarPtr(szRightStr)
      
          szRevStr VarPtr(szText),VarPtr(szExtra)
      
          MessageBox 0,VarPtr(szExtra),VarPtr(sztTl),0
      
        ' -----------
        ' Array copy
        ' -----------
          redim aLong&(1 to 10000)
          redim aNext&(1 to 10000)
      
          lpAr1 = VarPtr(aLong&(1))
          lpAr2 = VarPtr(aNext&(1))
      
          aLong&(5678) = 1234
      
          MemCopyD lpAr1,lpAr2,40000
      
          Result$ = str$(aNext&(5678))
      
          MessageBox 0,StrPtr(Result$),VarPtr(sztTl),0
      
          FUNCTION = 0
      
      END FUNCTION
      
      ' #########################################################################
      
      SUB szCatStr(ByVal lpszSource as LONG, ByVal lpszAdd as LONG)
      
          #REGISTER NONE
      
          LOCAL ln1 as DWORD
      
          ln1 = szLen(lpszSource)
      
          ! mov esi, lpszAdd
          ! mov edi, lpszSource
          ! add edi, ln1
      
        csSt:
          ! mov al, [esi]
          ! inc esi
          ! mov [edi], al
          ! inc edi
          ! test al, al       ; test for zero
          ! jne csSt
      
      END SUB
      
      ' ###########################################################################
      
      FUNCTION szLen(ByVal lpszString as LONG) as LONG
      
          #REGISTER NONE
      
          LOCAL retval as LONG
      
          ! mov     eax,lpszString         ; get pointer to string
          ! lea     edx,[eax+3]            ; pointer+3 used in the end
        lnSt:     
          ! mov     ebx,[eax]              ; read first 4 bytes
          ! add     eax,4                  ; increment pointer
          ! lea     ecx,[ebx-&H01010101]   ; subtract 1 from each byte
          ! not     ebx                    ; invert all bytes
          ! and     ecx,ebx                ; and these two
          ! and     ecx,&H80808080
          ! jz      lnSt                   ; no zero bytes, continue loop
          ! test    ecx,&H00008080         ; test first two bytes
          ! jnz     lnOut
          ! shr     ecx,16                 ; not in the first 2 bytes
          ! add     eax,2
        lnOut:     
          ! shl     cl,1                   ; use carry flag to avoid branch
          ! sbb     eax,edx                ; compute length
      
          ! mov FUNCTION, eax
          
      END FUNCTION
      
      ' ###########################################################################
      
      SUB MemCopyD(ByVal src as LONG, _
                   ByVal dst as LONG, _
                   ByVal ln as LONG)
      
          #REGISTER NONE
      
            ! cld
      
            ! mov esi, src
            ! mov edi, dst
            ! mov ecx, ln
      
            ! shr ecx, 2
            ! rep movsd
      
            ! mov ecx, ln
            ! and ecx, 3
            ! rep movsb
      
      END SUB
      
      ' ###########################################################################
      
      SUB szLeft(ByVal lpszSource  as LONG, _
                 ByVal lpszTarget  as LONG, _
                 ByVal ln as LONG)
      
          #REGISTER NONE
      
          ! cld
      
          ! mov esi, lpszSource
          ! mov edi, lpszTarget
          ! mov ecx, ln
      
          ! shr ecx, 2
          ! rep movsd
      
          ! mov ecx, ln
          ! and ecx, 3
          ! rep movsb
      
          ! mov al, 0
          ! mov [edi], al
      
      END SUB
      
      ' ###########################################################################
      
      SUB szMid(ByVal lpszSource  as LONG, _
                ByVal lpszTarget  as LONG, _
                ByVal stPos       as LONG, _
                ByVal ln          as LONG)
      
          #REGISTER NONE
      
          ! cld
      
          ! mov esi, lpszSource
          ! mov edi, lpszTarget
          ! add esi, stPos
          ! mov ecx, ln
      
          ! shr ecx, 2
          ! rep movsd
      
          ! mov ecx, ln
          ! and ecx, 3
          ! rep movsb
      
          ! mov al, 0
          ! mov [edi], al
      
      END SUB
      
      ' ###########################################################################
      
      SUB szRight(ByVal lpszSource  as LONG, _
                  ByVal lpszTarget  as LONG, _
                  ByVal ln as LONG)
      
          #REGISTER NONE
      
          LOCAL ln1 as DWORD
      
          ln1 = szLen(lpszSource)
      
          ! cld
      
          ! mov esi, lpszSource
          ! add esi, ln1
          ! sub esi, ln
          ! mov edi, lpszTarget
          ! mov ecx, ln
      
          ! shr ecx, 2
          ! rep movsd
      
          ! mov ecx, ln
          ! and ecx, 3
          ! rep movsb
      
          ! mov al, 0
          ! mov [edi], al
      
      END SUB
      
      ' ###########################################################################
      
      SUB szRevStr(ByVal lpszSource as LONG,ByVal lpszTarget as LONG)
      
          #REGISTER NONE
      
          LOCAL ln as LONG
      
          ln = szLen(lpszSource)
      
          ! mov esi, lpszSource
          ! mov edx, esi        ; put in edx for comparison
          ! dec edx
          ! add esi, ln         ; add len to source address
          ! dec esi
          ! mov edi, lpszTarget
      
        rsSt:
          ! mov al, [esi]
          ! dec esi
          ! mov [edi], al
          ! inc edi
          ! cmp esi, edx
          ! jne rsSt
      
          ! mov al, 0
          ! mov [edi], al       ; write terminator
      
      END SUB
      
      ' ###########################################################################
    hutch at movsd dot com
    The MASM Forum

    www.masm32.com
Working...
X