Fast integer multiply in the 2 to 10 range in PowerBASIC.

Started by hutch--, December 20, 2009, 05:27:01 PM

Previous topic - Next topic

hutch--

For the obvious reason, this type of code is identical to how these things are done in MASM and any similar assembler. MUL and IMUL still tend tro be slow, even on late model hardware and if you have a task that requires a fixed multiply in this range, you will see speed improvements by using the alternatives.

This is the test piece.


#IF 0  ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    Build with PBCC50

    FUNCTION LIST
        1. cout     console display with C escape support
        2. pause    wait for a key press to continue
        3. sstr     convert a SIGNED integer to a basic string
        4. ustr     convert an UNSIGNED integer to a basic string
        5. atoi     convert a string to an UNSIGNED integer
        6. atol     convert a string to a SIGNED integer

#ENDIF ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

FUNCTION PBmain as LONG

    #REGISTER NONE

    LOCAL svar as LONG
    LOCAL uvar as DWORD

    cout "\nFast multiply example in the\nPowerBASIC Console Compiler PBCC50\n\n"

    ! mov eax, 10
    ! add eax, eax              ' mul by 2
  ' ==================
    ! mov svar, eax
    cout sstr(svar)
  ' ==================

    ! mov eax, 10
    ! lea eax, [eax+eax*2]      ' mul by 3
  ' ==================
    ! mov svar, eax
    cout sstr(svar)
  ' ==================

    ! mov eax, 10
    ! lea eax, [eax*4]          ' mul by 4
  ' ==================
    ! mov svar, eax
    cout sstr(svar)
  ' ==================

    ! mov eax, 10
    ! lea eax, [eax+eax*4]      ' mul by 5
  ' ==================
    ! mov svar, eax
    cout sstr(svar)
  ' ==================

    ! mov eax, 10
    ! lea eax, [eax+eax*2]      ' mul by 6
    ! add eax, eax
  ' ==================
    ! mov svar, eax
    cout sstr(svar)
  ' ==================

    ! mov eax, 10
    ! mov ecx, eax
    ! lea eax, [eax*8]          ' mul by 7
    ! sub eax, ecx
  ' ==================
    ! mov svar, eax
    cout sstr(svar)
  ' ==================

    ! mov eax, 10
    ! lea eax, [eax*8]          ' mul by 8
  ' ==================
    ! mov svar, eax
    cout sstr(svar)
  ' ==================

    ! mov eax, 10
    ! lea eax, [eax+eax*8]      ' mul by 9
  ' ==================
    ! mov svar, eax
    cout sstr(svar)
  ' ==================

    ! mov eax, 10
    ! lea eax, [eax+eax*4]      ' mul by 10
    ! add eax, eax
  ' ==================
    ! mov svar, eax
    cout sstr(svar)
  ' ==================

    pause

    FUNCTION = 0

End FUNCTION

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

    DECLARE FUNCTION cc_out CDECL LIB "MSVCRT.DLL" ALIAS "puts" (BYVAL ptxt AS DWORD) AS DWORD

SUB cout(a$)

  ' ***** Supported escapes *****
  ' \0 = ascii zero             0
  ' \t = tab                    9
  ' \n = newline               10
  ' \r = carriage return       13
  ' \q = double quote          34
  ' \\ = backslash             92
  ' *****************************

    #REGISTER NONE

    LOCAL src as DWORD
    LOCAL dst as DWORD
    LOCAL sln as DWORD

    src = StrPtr(a$)

    ! mov esi, src
    ! mov edi, src

  stlp:
    ! mov al, [esi]
    ! add esi, 1

    ! cmp al, "\"
    ! jne nxt

' ¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤

    ! cmp BYTE PTR [esi], "n"
    ! jne lb1
    ! add esi, 1
    ! mov BYTE PTR [edi], 10
    ! add edi, 1
    ! jmp stlp
  lb1:

    ! cmp BYTE PTR [esi], "r"
    ! jne lb2
    ! add esi, 1
    ! mov BYTE PTR [edi], 13
    ! add edi, 1
    ! jmp stlp
  lb2:

    ! cmp BYTE PTR [esi], "t"
    ! jne lb3
    ! add esi, 1
    ! mov BYTE PTR [edi], 9
    ! add edi, 1
    ! jmp stlp
  lb3:

    ! cmp BYTE PTR [esi], "0"
    ! jne lb4
    ! add esi, 1
    ! mov BYTE PTR [edi], 0
    ! add edi, 1
    ! jmp stlp
  lb4:

    ! cmp BYTE PTR [esi], "\"
    ! jne lb5
    ! add esi, 1
    ! mov BYTE PTR [edi], 92
    ! add edi, 1
    ! jmp stlp
  lb5:

    ! cmp BYTE PTR [esi], "q"
    ! jne lb6
    ! add esi, 1
    ! mov BYTE PTR [edi], 34
    ! add edi, 1
    ! jmp stlp
  lb6:

' ¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤

  nxt:
    ! mov [edi], al
    ! add edi, 1
    ! test al, al
    ! jnz stlp

    ! sub edi, src
    ! mov sln, edi

    cesc$ = left$(a$,sln)

    cc_out StrPtr(cesc$)

END SUB

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

    MACRO INPUT_HANDLE  = -10&
    DECLARE FUNCTION kbflush LIB "KERNEL32.DLL" ALIAS "FlushConsoleInputBuffer" ( _
                     BYVAL hConsoleInput AS DWORD) AS LONG
    DECLARE FUNCTION hStdIn LIB "KERNEL32.DLL" ALIAS "GetStdHandle" ( _
                     BYVAL nStdHandle AS DWORD) AS DWORD
    DECLARE FUNCTION SysYield LIB "KERNEL32.DLL" ALIAS "Sleep" ( _
                     BYVAL msWait AS DWORD) AS LONG
    DECLARE FUNCTION keypress CDECL LIB "MSVCRT.DLL" ALIAS "_kbhit" () as DWORD
    DECLARE FUNCTION putz CDECL LIB "MSVCRT.DLL" ALIAS "puts" (BYVAL ptxt AS DWORD) AS DWORD

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

SUB pause()

    txt$ = "Press any key to continue ...."
    putz StrPtr(txt$)
    kbflush hStdIn(INPUT_HANDLE)

  lbl0:
    SysYield 20
    keypress
    ! test eax, eax
    ! jz lbl0

END SUB

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

    DECLARE FUNCTION ltoa CDECL LIB "MSVCRT.DLL" ALIAS "_ltoa" ( _
                     ByVal lval as LONG,ByVal pstr as DWORD,ByVal radix as DWORD) as DWORD

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

FUNCTION sstr(ByVal lval as LONG) as STRING

    LOCAL astring as ASCIIZ * 32

    ltoa(lval,VarPtr(astring),10)

    FUNCTION = astring

End FUNCTION

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

    DECLARE FUNCTION c_ultoa CDECL LIB "MSVCRT.DLL" ALIAS "_ultoa" ( _
                     ByVal uint as DWORD,ByVal pstr as DWORD,ByVal radix as DWORD) as DWORD

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

FUNCTION ustr(ByVal uint as DWORD) as STRING

    LOCAL astring as ASCIIZ * 32

    c_ultoa(uint,VarPtr(astring),10)

    FUNCTION = astring

End FUNCTION

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

    DECLARE FUNCTION c_atoi CDECL LIB "MSVCRT.DLL" ALIAS "atoi" (ByVal ptxt as DWORD) as DWORD

FUNCTION atoi(number$) as DWORD

    FUNCTION = c_atoi(StrPtr(number$))

End FUNCTION

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

    DECLARE FUNCTION c_atol CDECL LIB "MSVCRT.DLL" ALIAS "atol" (ByVal ptxt as DWORD) as LONG

FUNCTION atol(number$) as LONG

    FUNCTION = c_atol(StrPtr(number$))

End FUNCTION

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

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