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
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤