With a number of macros, you can do much more with a FASTPROC, the technique below has macros for up to 16 arguments and the bare minimum stack frame.
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
#include "\basic\include\win32api.inc"
MACRO asm4(procedure,arg1,arg2,arg3,arg4)
! push arg4
! push arg3
! push arg2
! push arg1
! call procedure
END MACRO
MACRO FUNCTION ApiPtr(DllName,ProcName)
END MACRO = GetProcAddress(LoadLibrary(DllName),ProcName)
MACRO FUNCTION pBas(quoted)
MACROTEMP basstr
LOCAL basstr as STRING
basstr = quoted
END MACRO = StrPtr(basstr)
MACRO bp0 = DWORD PTR [ebp+8]
MACRO bp1 = DWORD PTR [ebp+12]
MACRO bp2 = DWORD PTR [ebp+16]
MACRO bp3 = DWORD PTR [ebp+20]
MACRO bp4 = DWORD PTR [ebp+24]
MACRO bp5 = DWORD PTR [ebp+28]
MACRO bp6 = DWORD PTR [ebp+32]
MACRO bp7 = DWORD PTR [ebp+36]
MACRO bp9 = DWORD PTR [ebp+40]
MACRO bp10 = DWORD PTR [ebp+44]
MACRO bp11 = DWORD PTR [ebp+48]
MACRO bp12 = DWORD PTR [ebp+52]
MACRO bp13 = DWORD PTR [ebp+56]
MACRO bp14 = DWORD PTR [ebp+60]
MACRO bp15 = DWORD PTR [ebp+64]
MACRO StackFrame = db 85,139,236
MACRO ExitFrame = db 139,229,93
GLOBAL pMessageBox as DWORD
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION PBmain as LONG
LOCAL pttl as DWORD
LOCAL pmsg as DWORD
pMessageBox = ApiPtr("user32.dll","MessageBoxA")
pmsg = pBas("Testing a MessageBox in a FASTPROC")
pttl = pBas("Howdy Folks")
asm4(mBox,0,pmsg,pttl,%MB_OK)
End FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FASTPROC mBox
PREFIX "!"
StackFrame ; create stack frame
push bp3
push bp2
push bp1
push bp0
call pMessageBox
ExitFrame ; exit stack frame
ret 16 ; balance the stack on exit
END PREFIX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤