I have recently been posting some tutorial level examples in the PB peer forum but unfortunately the lingering dead have struck again so I will post the examples here where assembler programmers are protected from the idiot fringe.
This example is a very simple empty console application designed primarily for developing and testing assembler subs and functions in PowerBASIC. It is aimed at much the same level of simplicity as a MASM console application where you can concentrate on the algo design without having to climb over the normal mountain of GUI code to get it up and going. The template prototypes a number of simple conversions directly out of MSVCRT
Here is the PBCC template.
#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 "\n\tTestbed for Assembler Programming in\n\tthe PowerBASIC Console Compiler PBCC50\n\n"
' ---------------------------------------------
' conversion tests string to integer to string
' NOTE
' you only use these functions on 32 bit values
' ---------------------------------------------
svar = atol("-12345678") ' ascii to LONG conversion
longint$ = sstr(svar) ' LONG to ascii conversion
cout longint$
uvar = atoi("4000000000") ' ascii to DWORD conversion
uint$ = ustr(uvar) ' DWORD to ascii conversion
cout uint$
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
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Hi Hutch,
unfortunately at the moment I'm unable to understand
what you have produced, but my IT instinct tells me it is a real
neat and good stuff.
I'll try to study it and learn something from it.
My intuition is that it can be used to learn some ASM code in a simplified context.
Thanks a lot for your patience.
Frank
Frank,
If you own one of the PB compilers this style of code works well and it makes learning assembler programming a bit easier for people with a basic background. The biggest problem for anyone coming from another language is to remove enough of the level of assumption to try doing things in very basic ways but in this case the language handles true low level code if you can get the swing of it.
I am currently writing a complex project in PB which generates MASM code and it is the right language to do this as it has exceptional string handling which is well suited for code generation and while there is not much asm in it, these code generators do work well.
Quote from: hutch-- on April 19, 2010, 01:17:56 AM
Frank,
If you own one of the PB compilers this style of code works well and it makes learning assembler programming a bit easier for people with a basic background. The biggest problem for anyone coming from another language is to remove enough of the level of assumption to try doing things in very basic ways but in this case the language handles true low level code if you can get the swing of it.
I am currently writing a complex project in PB which generates MASM code and it is the right language to do this as it has exceptional string handling which is well suited for code generation and while there is not much asm in it, these code generators do work well.
I totally agree. In fact this will be my main path for learning some ASM for now.
Frank