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"