Page 1 of 2
restore label as a parameter to a procedure?
Posted: Tue Dec 16, 2008 2:47 pm
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
Posted: Tue Dec 16, 2008 2:49 pm
by Kaeru Gaman
> label be used as a paremeter in a procedure
yes: ?label
> restore work with a variable
no
Posted: Tue Dec 16, 2008 3:00 pm
by kinglestat
thanks
Posted: Tue Dec 16, 2008 3:00 pm
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.
Posted: Tue Dec 16, 2008 3:18 pm
by kinglestat
many thanks
I hadnt even thought of how to go around it yet
was more worried about the steaks!
cheers
Re: restore label as a parameter to a procedure?
Posted: Sun Mar 14, 2010 6:50 am
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.
Re: restore label as a parameter to a procedure?
Posted: Fri Sep 23, 2011 11:14 pm
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
Re: restore label as a parameter to a procedure?
Posted: Fri Sep 23, 2011 11:53 pm
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.
Re: restore label as a parameter to a procedure?
Posted: Sat Sep 24, 2011 12:04 am
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.
Re: restore label as a parameter to a procedure?
Posted: Sat Sep 24, 2011 12:29 am
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.

Re: restore label as a parameter to a procedure?
Posted: Mon Jan 30, 2012 2:53 am
by skywalk
Argg!

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
Re: restore label as a parameter to a procedure?
Posted: Mon Jan 30, 2012 3:40 am
by Demivec
skywalk wrote:Argg!

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
Re: restore label as a parameter to a procedure?
Posted: Mon Jan 30, 2012 5:28 am
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.
Re: restore label as a parameter to a procedure?
Posted: Mon Jan 30, 2012 3:54 pm
by luis
Thanks demivec, I don't know why at the time I didn't use the label instead of the fixed values

Re: restore label as a parameter to a procedure?
Posted: Sun Jan 24, 2016 9:45 am
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