• Welcome to Powerbasic Museum 2020-B.
 

Example of assembler procedures with no stack frame.

Started by Steve Hutchesson, February 06, 2010, 08:36:05 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Steve Hutchesson

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

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