restore label as a parameter to a procedure?

Just starting out? Need help? Post your questions and find answers here.
kinglestat
Enthusiast
Enthusiast
Posts: 732
Joined: Fri Jul 14, 2006 8:53 pm
Location: Malta
Contact:

restore label as a parameter to a procedure?

Post by kinglestat »

I had a macro to populate an array using

Restore label

::
::
::
label:

can label be used as a paremeter in a procedure AND restore work with a variable?

cheers
I may not help with your coding
Just ask about mental issues!

http://www.lulu.com/spotlight/kingwolf
http://www.sen3.net
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

> label be used as a paremeter in a procedure

yes: ?label

> restore work with a variable

no
oh... and have a nice day.
kinglestat
Enthusiast
Enthusiast
Posts: 732
Joined: Fri Jul 14, 2006 8:53 pm
Location: Malta
Contact:

Post by kinglestat »

thanks
I may not help with your coding
Just ask about mental issues!

http://www.lulu.com/spotlight/kingwolf
http://www.sen3.net
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Either use a macro or...

Code: Select all

Procedure myRestore(address)
  !MOV EAX, [ESP+PS0]
  !MOV [PB_DataPointer],EAX
EndProcedure

a = ?NumericalData2

  myRestore(a)
  Read.l a
  Read.l b

  Debug a
  End  
  
  DataSection
    NumericalData1:    
      Data.l 100, 200
      
    NumericalData2:    
      Data.l 1000, 2000
  EndDataSection
If you alter the procedure's parameters, just make sure that address is the first parameter.
I may look like a mule, but I'm not a complete ass.
kinglestat
Enthusiast
Enthusiast
Posts: 732
Joined: Fri Jul 14, 2006 8:53 pm
Location: Malta
Contact:

Post by kinglestat »

many thanks
I hadnt even thought of how to go around it yet
was more worried about the steaks!

cheers
I may not help with your coding
Just ask about mental issues!

http://www.lulu.com/spotlight/kingwolf
http://www.sen3.net
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: restore label as a parameter to a procedure?

Post by skywalk »

Very cool srod!
This helped me solve my autogenerating menu problem.

Any chance this will make it as a PureBasic feature?
Or is this a limitation of single pass compiler (same reason for putting declares up top)?

I am autogenerating my menus based on elements/instructions in the DataSection.
My approach needs to pass the Data Label Address into a procedure.

Code fragment here...

Code: Select all

Procedure RestoreUsingVar(LabelAddress.i)
  !MOV EAX, [ESP+PS0]
  !MOV [PB_DataPointer],EAX
EndProcedure

Procedure.i MenuLoad(hWnd.i, mnuDataLabel.i, mnuID.i, Array mnu.MenuInfo(1))
  Protected.i i,k,sck,fk,ri
  Protected.s m1,m2,m3,sc
  ;Restore mnuDataLabel                 ;<--- This does not work :(
  RestoreUsingVar(mnuDataLabel)
  Repeat
    With mnu(k)
      Read.s m1
;~~~
; more code here
;~~~
    EndWith
  Until m1 = "E" Or m1 = ""
  ProcedureReturn k
EndProcedure

nMenuLines = MenuLoad(hOne, ?Menu_DataOne, #mnuOne, mnuOne())

End
DataSection
  Menu_DataOne:
  ;      Type, Text, ShortCut(@ = Alt+, $ = Shift+, ^ = Ctrl+)
  Data.s "T","&File"
  Data.s     "&Close","^Q"
  Data.s "T","&Help"  
  Data.s     "K","&About","F1"
  Data.s "E" ; EndMenu

  Menu_DataTwo:
  Data.s "T","&File"
  Data.s     "&Close"
  Data.s "T","&Help"  
  Data.s     "K","&About","F1"
  Data.s "E" ; EndMenu
EndDataSection
I can post the whole thing if anybody cares. Really only makes sense if you have large menus > 25 entries and nested etc.
I type in the menu constructs in the DataSection and the code builds it straight away.
Then, to handle the menu events, I copy and paste the data.s sections into a select case block.
The cases are strings, but it is self-documenting nonetheless.

I am now trying to autogenerate gadgets/windows based on instructions in the DataSection.
Last edited by skywalk on Sun Nov 25, 2012 8:55 pm, edited 1 time in total.
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: restore label as a parameter to a procedure?

Post by luis »

EDIT: updated for C backend (6.01 B4)

Code: Select all

DataSection
 Data.i 1, 2, 3
here:
 Data.i 4, 5, 6
EndDataSection

Procedure RestoreEx (*ptr) 
CompilerIf (#PB_Compiler_Backend = #PB_Backend_Asm)
 CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
  !mov eax, [p.p_ptr]
  !mov [PB_DataPointer], eax
  CompilerElse   
  !mov rax, [p.p_ptr]
  !mov [PB_DataPointer], rax  
 CompilerEndIf
CompilerElse
  !pb_datapointer = (unsigned char *) p_ptr;
CompilerEndIf
EndProcedure

*here = ?here 

RestoreEx (*here)

Read.i x

Debug x ; 4 
Last edited by luis on Sat Feb 18, 2023 9:32 pm, edited 1 time in total.
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: restore label as a parameter to a procedure?

Post by skywalk »

Hi luis,
Does your code also work if there are XIncludeFiles?
It's been a while, but I was unable to use srod's Restore tip in that case.
Had to resort back to pointer math on the passed label when stepping through my DataSections in a Procedure.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: restore label as a parameter to a procedure?

Post by luis »

skywalk wrote:Hi luis,
Does your code also work if there are XIncludeFiles?
I'm not sure what the implications of that could been to affect that code.
I don't see why shouldn't work but maybe I'm not considering something ?

Uhmm... for the original srod's routine probably the problem you encountered was it would work only if it's the first proc in your program, because the PS0 is really a constant generated by the compiler for each proc and the numeric part is incremented each time (roughly speaking). I assume at the time he adapted the output of the compiler.

So that code will not work if the proc is not the first (PS"0").

If I didn't make (didn't have ? what's the correct one ? LOL) some oversight this should work.
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: restore label as a parameter to a procedure?

Post by skywalk »

Thanks luis!
You are correct. Your procedure works with XIncludeFiles where srod's use of "PS0" caused an incorrect label.
Wow, how simple a correction. :oops: :)
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: restore label as a parameter to a procedure?

Post by skywalk »

Argg! :cry: I cannot figure this out?
Why do I get an IMA when using RestoreX_case()?
The only difference is CompilerCase statements?

Code: Select all

EnableExplicit
Macro NEXTDATA_Str(DataLabel)
  ; Use this if RestoreX() fails with newer PB versions.
  *DataLabel + (MemoryStringLength(*DataLabel) + 1) * SizeOf(Character)
EndMacro

Procedure RestoreX_case(DataLabel.i)
  CompilerSelect #PB_Compiler_Processor
  CompilerCase #PB_Processor_x86
    !mov eax, [esp+8]
    !mov [PB_DataPointer], eax
  ;CompilerCase #PB_Processor_x64
  CompilerDefault ;#PB_Processor_x64
    !mov rax, [rsp+64]
    !mov [PB_DataPointer], rax
  CompilerEndSelect
EndProcedure

Procedure RestoreX_if(DataLabel.i)
  CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
    !mov eax, [esp+8]
    !mov [PB_DataPointer], eax
  CompilerEndIf
  CompilerIf (#PB_Compiler_Processor = #PB_Processor_x64)
    !mov rax, [rsp+64]
    !mov [PB_DataPointer], rax
  CompilerEndIf
EndProcedure

Procedure RestoreX_Luis(DataLabel.i)
  CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
    !mov eax, [esp+8]
    !mov [PB_DataPointer], eax
  CompilerElse
    !mov rax, [rsp+64]
    !mov [PB_DataPointer], rax
  CompilerEndIf
EndProcedure

Procedure.i MenuLoad(mnuDataLabel.i)
  Protected.i *p = mnuDataLabel
  Protected.s m$
  ;Restore mnuDataLabel                 ;<--- This does not work :(
  Debug PeekS(mnuDataLabel)
  Repeat
    m$ = PeekS(*p):   NEXTDATA_Str(p)
    Debug m$
  Until m$ = "E" Or m$ = ""
EndProcedure

Procedure.i MenuLoad_RestoreX(mnuDataLabel.i, Mode.i=0)
  Protected.s m$
  Select mode
  Case 0
    RestoreX_luis(mnuDataLabel)
  Case 1
    RestoreX_if(mnuDataLabel)
  Case 2
    RestoreX_case(mnuDataLabel)
  EndSelect
  Debug PeekS(mnuDataLabel)
  Repeat
    Read.s m$
    Debug m$
  Until m$ = "E" Or m$ = ""
EndProcedure

Debug "--- Menu2 ---"
MenuLoad(?Menu2)
Debug "--- RestoreX_Luis ---"
MenuLoad_RestoreX(?Menu2,0)
Debug "--- RestoreX_if ---"
MenuLoad_RestoreX(?Menu2,1)
Debug "--- RestoreX_case ---"
MenuLoad_RestoreX(?Menu2,2)

DataSection
  Menu1:
  Data.s "T","&File"
  Data.s     "&Close","^Q"
  Data.s "E" ; EndMenu

  Menu2:
  Data.s "T","&Options"
  Data.s     "&None"
  Data.s "E" ; EndMenu
EndDataSection
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Demivec
Addict
Addict
Posts: 4086
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: restore label as a parameter to a procedure?

Post by Demivec »

skywalk wrote:Argg! :cry: I cannot figure this out?
Why do I get an IMA when using RestoreX_case()?
The only difference is CompilerCase statements?
There may be other differences.

Just for completeness, here is the assembly code that was generated:

Code: Select all

; Procedure RestoreX_case(DataLabel.i)
macro MP0{
_Procedure0:
  PS0=4                                                                                                                                                                                                                                                     
; CompilerSelect #PB_Compiler_Processor
; CompilerCase #PB_Processor_x86
; !MOV Eax, [esp+8]
p.v_DataLabel equ esp+PS0+0
MOV Eax, [esp+8]
; !MOV [PB_DataPointer], Eax
MOV [PB_DataPointer], Eax
;CompilerCase #PB_Processor_x64
; CompilerDefault ;#PB_Processor_x64
; EndProcedure
  XOR    eax,eax
_EndProcedure1:
  RET    4
}
; 
; Procedure RestoreX_if(DataLabel.i)
macro MP2{
_Procedure2:
  PUSH   ebx
  PS2=8                                                                                                                                                                                                                                           
; CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
; !MOV Eax, [esp+8]
p.v_DataLabel equ esp+PS2+0
MOV Eax, [esp+8]
; !MOV [PB_DataPointer], Eax
MOV [PB_DataPointer], Eax
; CompilerEndIf
; CompilerIf (#PB_Compiler_Processor = #PB_Processor_x64)
; EndProcedure
  XOR    eax,eax
_EndProcedure3:
  POP    ebx
  RET    4
}
You'll notice that the variable (DataLabel) is at esp + 4 in the problem case and at esp + 8 in the one that works.


Using the variable name instead of an assumed offset works (only tested on x86):

Code: Select all

Procedure RestoreX_case(DataLabel.i)
  CompilerSelect #PB_Compiler_Processor
    CompilerCase #PB_Processor_x86
      !MOV Eax, [p.v_DataLabel]
      !MOV [PB_DataPointer], Eax
      ;CompilerCase #PB_Processor_x64
    CompilerDefault ;#PB_Processor_x64
      !MOV rax, [p.v_DataLabel]
      !MOV [PB_DataPointer], rax
  CompilerEndSelect
EndProcedure
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: restore label as a parameter to a procedure?

Post by skywalk »

Wow, I did a compare on the 2 ASM's but didn't catch that.
Is this related to the order of procedures or is the CompilerCase handled wrong?
I only stumbled on this since there isn't a CompilerElseIf.

Thanks, Demivec, I'll check tomorrow.
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: restore label as a parameter to a procedure?

Post by luis »

Thanks demivec, I don't know why at the time I didn't use the label instead of the fixed values :?:
"Have you tried turning it off and on again ?"
A little PureBasic review
Ramses800
User
User
Posts: 27
Joined: Wed Nov 05, 2014 3:12 pm
Location: Sweden

Re: restore label as a parameter to a procedure?

Post by Ramses800 »

Thanks so much for this tip, srod & luis!
Now I can hide strings as numbers in the data section easily together with a small app that generates the data section from any(well,ASCII) string.

Code: Select all

Procedure RestoreEx (*address) 
 CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
  !mov eax, [p.p_address]
  !mov [PB_DataPointer], eax
  CompilerElse   
  !mov rax, [p.p_address]
  !mov [PB_DataPointer], rax  
 CompilerEndIf
EndProcedure

Procedure.s HiddenString(Label)
  Define lStringLength.l, lCtrl.l
  Define sReturn.s
  Define lCharacter.l
  ; restore label
  RestoreEx(label)
  ; read length of hidden string from first number
  Read.l lStringLength
  For lCtrl=1 To lStringLength
    ; read each number as character
    Read.l lCharacter
    sReturn=sReturn + Chr(lCharacter)
  Next
  ProcedureReturn sReturn
EndProcedure

CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)  
  MessageRequester("HiddenString(x86)",HiddenString(?MyHiddenString))
CompilerElse  
  MessageRequester("HiddenString(x64)",HiddenString(?MyHiddenString))
CompilerEndIf


DataSection
  MyHiddenString:
  ; First number is the length of the string, the consecutive numbers are ASCII for each character
  Data.l 21,78,111,119,32,121,111,117,32,99,97,110,39,116,32,115,101,101,32,109,101,33
EndDataSection

Code: Select all

Procedure.s GenerateDataSection(sLabelName.s,sString.s)
  Define sString.s
  Define lCtrl.l, lStringLength.l
  Define sReturn.s
  lStringLength=Len(sString)
  sReturn="DataSection" + #CRLF$
  sReturn= sReturn +  sLabelName + ":"  + #CRLF$
  sReturn= sReturn + "Data.l " + Str(lStringLength) 
  For lCtrl=1 To Len(sString)
    sReturn=sReturn + "," + Asc(Mid(sString,lCtrl,1))
  Next
  sReturn = sReturn + #CRLF$ + "EndDataSection"
  ProcedureReturn sReturn
EndProcedure
Generate the data section and copy/paste it into the code that use the hidden string.

Code updated after remark from sys64802
Last edited by Ramses800 on Sun Jan 24, 2016 4:25 pm, edited 2 times in total.
Former VB6 developer adventuring in a brave, new Purebasic world!
Post Reply