This is a test piece to show how to use assembler procedures written in MASM within PowerBASIC. As PB excludes module level scope by design for protection reasons, it takes a minor workaround to do it by writing all of the procedures within a SUB, entering the SUB once to get the label addresses and storing them in global DWORD variables. The procedures are them called in code using the CALL\RET notation. It works just as well with procedures outputted by the CL C compiler as log as you kow how to clean up the messy output.
Here is the example.
#IF 0 ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
No stack frame procedures in PowerBASIC
#ENDIF ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
GLOBAL slnth as DWORD
GLOBAL lower as DWORD
GLOBAL upper as DWORD
GLOBAL monos as DWORD
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION PBmain as LONG
#REGISTER NONE
LOCAL pstr as DWORD
LOCAL lstr as DWORD
LOCAL szText as ASCIIZ * 96
WriteProcAddresses ' get the address of each procedure
szText = " THIS IS A STRING TO TEST THE STRING LENGTH ALGO "
StdOut szText
pstr = VarPtr(szText)
! push pstr
! call slnth ' get string length
! mov lstr, eax
StdOut "Length ="+str$(lstr)
! push pstr
! call lower ' convert it to lower case
StdOut szText
! push pstr
! call upper ' convert it to upper case
StdOut szText
! push pstr
! call monos ' clean up the spacing and other junk
StdOut szText
! push pstr
! call slnth ' get string length
! mov lstr, eax
StdOut "Length ="+str$(lstr)
StdOut "Press any key to say Bye Bye ...."
Do
Sleep 10
Loop while inkey$ = ""
FUNCTION = 0
End FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
SUB WriteProcAddresses()
#REGISTER NONE
slnth = CodePtr(proc1)
lower = CodePtr(proc2)
upper = CodePtr(proc3)
monos = CodePtr(proc4)
Exit SUB
' --------------------------------------------------------
' string length
' --------------------------------------------------------
#align 16
proc1:
! mov eax, [esp+4]
! sub eax, 4
lbl0:
! 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 lbl0
! 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
' --------------------------------------------------------
' lower case
' --------------------------------------------------------
#align 16
proc2:
! mov eax, [esp+4]
! dec eax
lbl4:
! add eax, 1
! cmp BYTE PTR [eax], 0
! je lbl5
! cmp BYTE PTR [eax], "A"
! jb lbl4
! cmp BYTE PTR [eax], "Z"
! ja lbl4
! add BYTE PTR [eax], 32
! jmp lbl4
lbl5:
! mov eax, [esp+4]
! ret 4
' --------------------------------------------------------
' upper case
' --------------------------------------------------------
#align 16
proc3:
! mov eax, [esp+4]
! dec eax
lbl6:
! add eax, 1
! cmp BYTE PTR [eax], 0
! je lbl7
! cmp BYTE PTR [eax], "a"
! jb lbl6
! cmp BYTE PTR [eax], "z"
! ja lbl6
! sub BYTE PTR [eax], 32
! jmp lbl6
lbl7:
! mov eax, [esp+4]
! ret 4
' --------------------------------------------------------
' monospace and clean up text
' --------------------------------------------------------
#align 16
proc4:
! push ebx
! push esi
! push edi
! push ebp
! mov esi, 1
! mov edi, 32
! mov bl, 32
! mov ebp, 9
! mov ecx, [esp+20]
! xor eax, eax
! sub ecx, esi
! mov edx, [esp+20]
! jmp ftrim ; trim the start of the string
wspace:
! mov BYTE PTR [edx], bl ; always write a space
! add edx, esi
ftrim:
! add ecx, esi
! movzx eax, BYTE PTR [ecx]
! cmp eax, edi ; throw away space
! je ftrim
! cmp eax, ebp ; throw away tab
! je ftrim
! sub ecx, esi
stlp:
! add ecx, esi
! movzx eax, BYTE PTR [ecx]
! cmp eax, edi ; loop back on space
! je wspace
! cmp eax, ebp ; loop back on tab
! je wspace
! mov [edx], al ; write the non space character
! add edx, esi
! test eax, eax ; if its not zero, loop back
! jne stlp
! cmp BYTE PTR [edx-2], bl ; test for a single trailing space
! jne quit
! mov BYTE PTR [edx-2], 0 ; overwrite it with zero if it is
quit:
! mov eax, [esp+20]
! pop ebp
! pop edi
! pop esi
! pop ebx
! ret 4
' --------------------------------------------------------
END SUB
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤