Gosub Return macros
Posted: Sun Jun 30, 2013 11:21 pm
Redefined Gosub, Return, Goto macros for those that want them
your labels need to be defined with inline asm directive "!"
It uses Pb macro expansion to change the variables in the Fasm preprocesor directives
If you Gosub from within a select statement you need to specify the nest depth you're breaking out of
eg from a nest of two Selects statement Gosub(label,2) will assemble
And the Return(label) will automatically rebalance the stack
The Macros
your labels need to be defined with inline asm directive "!"
Code: Select all
!some_label:
If you Gosub from within a select statement you need to specify the nest depth you're breaking out of
eg from a nest of two Selects statement Gosub(label,2) will assemble
Code: Select all
;Gosub(label,2)
pop rax
pop rax
!jmp label
!label__Return:
!@@:
Code: Select all
!label:
;Return(label)
!push rax
!push rax
!jmp label__Return
The Macros
Code: Select all
;Reimplimentation of Gosub Return Goto for use in procedures via PB macro and fasm preprocesor directives
;Idle 2/4/2013 PB4.61 -> 5.20 x86/x64
;notes
;Uses inline asm labels prefix with "!" mark
;In some cases you will need to manually set depth parameter to suit the nesting level
;specifically when using Gossub and Goto from within Select statements
;v1.1
;removed the need to specify depth on return macro
Macro Gosub(label,depth=0) ;depth is needed to jmp and return out and in of nested selects
CompilerIf depth
CompilerIf SizeOf(integer) = 8
!label#_a=depth ;set a fasm preprocesor variable for the nest depth
!repeat label#_a
!pop rax ;assmebless pop rax
!end repeat
CompilerElse
!label#_a=depth
!repeat label#_a
!pop eax
!end repeat
CompilerEndIf
CompilerElse
!label#_a=0
CompilerEndIf
!jmp label
!if ~ defined label#__return | defined @f ;defines the return label if it's not defined
!label#__return: ;assembles return label
!@@: ;assembles anonymous label
!end if
EndMacro
Macro Return(label)
!if label#_a > 0
CompilerIf SizeOf(integer) = 8
!repeat label#_a
!push rax
!end repeat
CompilerElse
!repeat label#_a
!push eax
!end repeat
CompilerEndIf
!end if
!jmp label#__return
EndMacro
Macro Goto(label,depth=0) ;depth is needed to jmp and return out and in of nested selects
CompilerIf depth
CompilerIf SizeOf(integer) = 8
!repeat depth
!pop rax
!end repeat
CompilerElse
!repeat depth
!pop eax
!end repeat
CompilerEndIf
CompilerEndIf
!jmp label
EndMacro
Macro label(name)
!name#:
EndMacro
;example
Procedure b()
Protected v.i=5 ,x=6
Repeat
Select x
Case 6
Select v
Case 5
Gosub(l1,2) ;we are nested in 2 selects and exiting 2 levels to l1
Debug "after gosub Select l1 "+Str(v)
Case 6
Gosub(l2,2) ;
Debug "after gosub select l2 "+Str(v)
Default
Goto(l3,2) ;we are nested in 2 selects and exiting 2 levels to l3
EndSelect
EndSelect
ForEver
label(l3)
ProcedureReturn v
!l1: ;we jumped here from within the select statement using Gosub(l1,2) the stack pointer is ballanced
v+1 ;without the stack adjustment the protected variables wouldn't be accessible after the jump
Return(l1);l,2) ;return back to the select statement which is nested 2 levels using Return(l1,2) and restore the stack pointer
!l2:
v+1
Return(l2); ;comment out
Debug "goto l3"
Goto(l3) ;if you commented out Return(l2,2) you will jump to l3 from here no need to adjust depth
;you got here having exited the Select at Case 6 of Select v
EndProcedure
Procedure c()
w.s=Chr(65)
For i=Asc("B") To Asc("Z")
Gosub(cc)
Gosub(cc1)
w+Chr(i)
Next i
Debug w
ProcedureReturn
!cc:
w.s+"-"
Gosub(ee)
Return(cc)
!cc1:
w.s+"-"
Return(cc1)
!ee:
w.s+"."
Return(ee)
EndProcedure
b()
c()
Debug "done"