Announcement

Collapse
No announcement yet.

Test piece for using no stack frame assembler algorithms.

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

  • Test piece for using no stack frame assembler algorithms.

    This technique is an alternative when converting assembler algorithms from MASM or using the assembler output from a C compiler where there is no stack frame for the procedure.

    Converting bare mnemonic code to PB notation is relatively simple but manually editing a no stack frame procedure is not for the faint of heart and is very error prone.

    For the extra work of putting the code inside a normal basic SUB and having to make a call to the sub to obtain the procedure start addresses you get completely uncompromised assembler code performance and can routinely use code built in an entirely different compiler, in this case VC/VS C compiler output.

    The new #ALIGN directive removes the last advantage that a C compiler ever had over PB.

    Note that if you need to write mixed API/high level code and assembler you will produce far more reliable code if you use the normal stack frame SUB or FUNCTION but if you have pure mnemonic code from another source this technique allows you to use it with nothing more than a notation conversion.

    Code:
    #IF 0  ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
        8:02:22 PM Wednesday, November 18, 2009
    
        Build this test piece with PBWIN90
    
    #ENDIF ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    FUNCTION PBmain as LONG
    
        #REGISTER NONE
    
        LOCAL text as ASCIIZ * 64
        LOCAL ptxt as DWORD
        LOCAL var  as DWORD
    
        text = "This is a test"
        ptxt = VarPtr(text)
    
        init_asm_len_procs          ' get the asm procedure addresses
    
        szLen(ptxt)                 ' call the szLen function
        ! mov var, eax              ' write EAX to DWORD variable
    
        msgbox str$(var)
    
        ! mov eax, ptxt             ' copy ptxt variable to EAX
    
        szStrlen(eax)               ' call szStrlen using EAX register as argument
        ! mov var, eax
    
        msgbox str$(var)
    
        FUNCTION = 0
    
    End FUNCTION
    
    ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    #IF NOT %DEF(%proc_init_asm_len)
    
        %proc_init_asm_len = 1
    
        GLOBAL pszLen  as DWORD
        GLOBAL pstrlen as DWORD
    
        MACRO szLen(pstr)
          ! push pstr
          ! call pszLen
        END MACRO
    
        MACRO szStrlen(pstr)
          ! push pstr
          ! call pstrlen
        END MACRO
    
    ' ---------------------------
    
    SUB init_asm_len_procs()
    
        #REGISTER NONE
    
        pszLen  = CodePtr(asm_szlen)
        pstrlen = CodePtr(asm_StrLen)
    
      Exit SUB
    
      ' *****************************************************************
      ' simple string length algo unrolled by 4
      ' *****************************************************************
      #align 16
      asm_szlen:
        ! mov eax, [esp+4]
        ! sub eax, 4
    
      lb0:
        ! add eax, 4
        ! cmp BYTE PTR [eax], 0
        ! je lb1
        ! cmp BYTE PTR [eax+1], 0
        ! je lb2
        ! cmp BYTE PTR [eax+2], 0
        ! je lb3
        ! cmp BYTE PTR [eax+3], 0
        ! jne lb0
    
        ! sub eax, [esp+4]
        ! add eax, 3
        ! ret 4
    
      lb3:
        ! sub eax, [esp+4]
        ! add eax, 2
        ! ret 4
    
      lb2:
        ! sub eax, [esp+4]
        ! add eax, 1
        ! ret 4
    
      lb1:
        ! sub eax, [esp+4]
        ! ret 4
      ' *****************************************************************
      ' DWORD string length algo unrolled by 4
      ' *****************************************************************
      #align 16
      asm_StrLen:
        ! mov     eax, [esp+4]            ; get pointer to string
        ! lea     edx, [eax+3]            ; pointer+3 used in the end
        ! push    ebp
        ! push    edi
        ! mov     ebp, &H80808080
    
      slbl0:     
        ! 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, ebp
        ! jnz     slbl1
        ! 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, ebp
        ! jnz     slbl1
        ! 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, ebp
        ! jnz     slbl1
        ! 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, ebp
        ! jz      slbl0                   ; no zero bytes, continue loop
    
      slbl1:
        ! test    ecx, &H00008080         ; test first two bytes
        ! jnz     slbl2
        ! shr     ecx, 16                 ; not in the first 2 bytes
        ! add     eax, 2
    
      slbl2:
        ! shl     cl, 1                   ; use carry flag to avoid branch
        ! sbb     eax, edx                ; compute length
        ! pop     edi
        ! pop     ebp
    
        ! ret     4
      ' *****************************************************************
    
    End SUB
    
    #ENDIF
    
    ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    hutch at movsd dot com
    The MASM Forum

    www.masm32.com
Working...
X