Gosub Return macros

Share your advanced PureBasic knowledge/code with the community.
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Gosub Return macros

Post by idle »

Redefined Gosub, Return, Goto macros for those that want them
your labels need to be defined with inline asm directive "!"

Code: Select all

!some_label: 
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

Code: Select all

;Gosub(label,2)
pop rax 
pop rax  
!jmp label 
!label__Return:
!@@:   
And the Return(label) will automatically rebalance the stack

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"  
     
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Gosub Return macros

Post by luis »

I don't use gosub/return but this is chic :)

Thanks.

It's a shame the debugger skip the Gosub line and jump just before it, if only we had a Basic "NOP" to put inside the macro... uhmmmm.....
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Gosub Return macros

Post by idle »

I don't use them either but they can be useful.

there are still some restrictions on use though, like if you use them from within a Select
you need to ensure that you return to that point or it'll fail
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Gosub Return macros

Post by idle »

added GosubS() ReturnS() and GotoS() to be used from and to Select statements
Windows 11, Manjaro, Raspberry Pi OS
Image
yrreti
Enthusiast
Enthusiast
Posts: 546
Joined: Tue Oct 31, 2006 4:34 am

Re: Gosub Return macros

Post by yrreti »

I haven't used them yet in PB, but they can be useful.
Thank you for sharing this and along with some nice code commenting.

yrreti
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Gosub Return macros

Post by Kwai chang caine »

Oooh !!! a GOSUB like FRED try to do and remove immediately after :shock:
Thanks a lot IDLE 8)

Now... if you can create a procedure into a procedure like in Algol, Pascal, Ada, Scheme, Common Lisp, Python, C (no standard), D et Perl like this :

Code: Select all

Structure result
  hWnd.i
  String.s
EndStructure

Procedure.s EnumereProcess()

  Procedure EnumWindowsProc(hWnd, *lParam.result)
   Protected Title.s{260}
   GetWindowText_(hWnd, @Title, 260)

   If FindString(Title, *lParam\String)
     *lParam\String = Title
     *lParam\hWnd = hWnd
     ProcedureReturn #False
   EndIf

   ProcedureReturn #True

  EndProcedure

  Define param.result 
  param\String = " 5.10 ("
  
  If Not EnumWindows_(@EnumWindowsProc(), @param)
    ProcedureReturn "Found: " + param\String + " with hWnd: " + Str(param\hWnd)
  EndIf

EndProcedure
I marry you this weekend :mrgreen:

Image
ImageThe happiness is a road...
Not a destination
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Gosub Return macros

Post by idle »

It would be possible to do nested procedures with fasm macros
but it wouldn't be practicable due to the limitations of PB's macro processing.
So no marrying this weekend kcc! :lol:
Windows 11, Manjaro, Raspberry Pi OS
Image
LuCiFeR[SD]
666
666
Posts: 1033
Joined: Mon Sep 01, 2003 2:33 pm

Re: Gosub Return macros

Post by LuCiFeR[SD] »

good thing too, cause that would mean me and KCC would have to get divorced :)
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Gosub Return macros

Post by idle »

LuCiFeR[SD] wrote:good thing too, cause that would mean me and KCC would have to get divorced :)
:lol:
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Gosub Return macros

Post by idle »

Updated the macros to handle nesting depth
so they take the form
Gosub(label,depth=0) ;depth is needed to jmp and return out and in of nested selects
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Gosub Return macros

Post by Kwai chang caine »

but it wouldn't be practicable due to the limitations of PB's macro processing.
It's a shame :(
So no marrying this weekend kcc!
But i love you, when even :D
Thanks to share all your knowledge and have always original idea 8)
ImageThe happiness is a road...
Not a destination
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Gosub Return macros

Post by idle »

updated the macros and removed the need to specify a depth on Return
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
gurj
Enthusiast
Enthusiast
Posts: 693
Joined: Thu Jan 22, 2009 3:48 am
Location: china
Contact:

Re: Gosub Return macros

Post by gurj »

hope Gosub and Goto not use label, use address

Gosub ?label and Goto ?label
Gosub 199999 and Goto aaa.l

your to this:
Macro Gosub(address,depth=0)
Macro Return(address)
Macro Goto(address,depth=0)

see:
Chang 'Goto <label>' To 'Goto <?label>'
so will can use Variables for label
http://www.purebasic.fr/english/viewtop ... =3&t=68346
my pb for chinese:
http://ataorj.ys168.com
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Gosub Return macros

Post by idle »

gurj wrote:hope Gosub and Goto not use label, use address

Gosub ?label and Goto ?label
Gosub 199999 and Goto aaa.l

your to this:
Macro Gosub(address,depth=0)
Macro Return(address)
Macro Goto(address,depth=0)

see:
Chang 'Goto <label>' To 'Goto <?label>'
so will can use Variables for label
http://www.purebasic.fr/english/viewtop ... =3&t=68346
I don't think that will be possible as the labels address isn't fixed until the file is assembled.
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
gurj
Enthusiast
Enthusiast
Posts: 693
Joined: Thu Jan 22, 2009 3:48 am
Location: china
Contact:

Re: Gosub Return macros

Post by gurj »

in pb's code, ?label mean get address
but regret , pb not use :
Gosub ?label and Goto ?label
Gosub 199999 and Goto aaa.l
my pb for chinese:
http://ataorj.ys168.com
Post Reply