Skip to content
⌘ NSIS Forum Archive

Stack metafunctions

6 posts

Wabiloo#

Stack metafunctions

I've now written several dozen functions, and still, I haven't got the hand of the stack manipulation...

I was wondering, does anyone have any general "recipe" to start and finish a function and ensure that the state of the stack and $0-$R9 variables are unchanged at the end of the function (with the exception of the results that should end up on top of the stack).

So, if you know that
- The function takes x parameters/arguments
- The function will (internally) require y variables
- The function returns z results
what would be the general recipe?

So far, I've managed to get the first two constraints, but am failing to get the 3rd one working. I'd like to end up with results z_1,z_2,...,z_n in that order on the stack...
What I've got at the moment is z_1,z_n,z_n-1,...,z_2

Here is my code:
Name "Stack Test"
OutFile "StackTest.exe"
LoadLanguageFile "${NSISDIR}\Contrib\Language files\English.nlf"
!macro OpenStack _Arg1 _Arg2 _Arg3 _Res1 _Res2 _Res3 _Res4 _Res5
    Push ${_Arg1} 
    Push ${_Arg2}
    Push ${_Arg3}
    Call OpenStackFunction
    Pop ${_Res1}
    Pop ${_Res2}
    Pop ${_Res3}
    Pop ${_Res4}
    Pop ${_Res5}
!macroend
    
Function OpenStackFunction
    ; get parameters (3), 
    ; so that they get into $0, $1, $2
    Exch 2
    Exch $0
    Exch 2
    Exch 1
    Exch $1
    Exch 1
    Exch $2
    ; prepare rest of the internal variables (4 for 7 in total)
    Push $3
    StrCpy $3 ""
    Push $4
    StrCpy $4 ""
    Push $5
    StrCpy $5 ""
    Push $6
    StrCpy $6 ""
    
    ; Core of the function
    ; ... Do something ...
    
    ; Copy results (5) to $0 to $n
    StrCpy $0 "result-line1"
    StrCpy $1 "result-line2"
    StrCpy $2 "result-line3"
    StrCpy $3 "result-line4"
    StrCpy $4 "result-line5"
    
    ; Restore registers that don't hold results
    Pop $6
    Pop $5
    ; Push results on stack in right order
    ; and recover registers to initial state
    Exch $4 
    Exch 1    
    Exch $3
    Exch 2
    Exch $2
    Exch 3
    Exch $1
    Exch 4
    Exch $0 
FunctionEnd
Section ""
SectionEnd
Function .onInit 
    
    ; create a state for testing
    Push "stack3"
    Push "stack2"
    Push "stack1"
    StrCpy $0 "ex-r0"
    StrCpy $1 "ex-r1"
    StrCpy $2 "ex-r2"
    StrCpy $3 "ex-r3"
    StrCpy $4 "ex-r4"
    StrCpy $5 "ex-r5"
    StrCpy $6 "ex-r6"
    !insertmacro OpenStack "arg1" "arg2" "arg3" $R1 $R2 $R3 $R4 $R5
    ; display results
    MessageBox MB_OK "R1=$R1 - R2=$R2 - R3=$R3 - R4=$R4 - R5=$R5"    
    
FunctionEnd 
niteflyer#
I am currently working on a header file, which will care about passing and getting parameters before and after the function call.

The header will have a macro called InstallFunction which will generate the call interface dynamically.

Can you wait until monday ?
niteflyer#
To put it clear: InstallFunction will only do the stuff before and after call of the function for up to ten parameters.

Maybe I misunderstood you, or do you need a solution which does the prologue and epilogue INSIDE the function body ?
Afrow UK#
StrReplace pushes 3 items but only returns 1. To prevent the contents of the other 2 variables being removed, it Pushes them onto the stack before calling the function...



-Stu
niteflyer#
try nfUtils.nsh !

Have a look at this thread:

Are you a developer who uses NSIS to distribute your application? Are you a Winamp plug-in developer who wants to use NSIS to distribute your plug-in? Have suggestions for other people like you? This is the place.


${nfu.Function} and ${nfu.FunctionEnd} are designed to handle the passing of parameters inside the functionbody.

${nfu.!InstallFunction} will generate macros, which call a function and pass parameters before and after the call.