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
; ... Dosomething ...
;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 dont 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
>