Archive: Push/Pop/Exch my head is spinning!


Push/Pop/Exch my head is spinning!
I must have written about 100 functions, and each time, I spend longer trying to figure out what order to push/pop/exch at the start and even longer figuring out what order to push/pop/exch at the end. It takes ages to figure it out and makes my head spin :(

Is there an easy trick I am missing to write saving 4 variables, popping 3 then pushing 2 and restoring 4.

Is there any chance this is going to be somthing that is going to be addressed? I was thinking of function-local stack? Eg same everything on the local stack, pop what you want, do work, push what you want, restore from function-local stack. Easy?


If your problem is parameter-passing to functions with the stack, you should have look at http://nsis.sourceforge.net/NfUtils_header_file, especially http://nsis.sourceforge.net/NfUtils_...stallFunction,
http://nsis.sourceforge.net/NfUtils_...21AddFunction,
http://nsis.sourceforge.net/NfUtils_...e#nfu.Function and
http://nsis.sourceforge.net/NfUtils_...fu.FunctionEnd


Thanks looks like that will be useful. Please can you give me an example to fit the following:

!macro GetPoolNameFromPoolId P_ID P_RET
Push "${TMP_POOLS_FILE}"
Push "${COLUMN_POOL_ID}"
Push "${P_ID}"
Push "${COLUMN_POOL_NAME}"
Call GetMatchInFile
Pop ${P_RET}
!macroend

Function GetMatchInFile

# My temp variables are $0, $1, $2, $4
# Then push something on the stack

FunctionEnd


Untested:


The System plug-in can create a private stack for your function. See System::Store usage in Examples\System.


I was just about to leave the office when I got notified of your 2nd post, so I was not really concentrated with my reply. I forgot some essentials (in red), OutFile is still missing:


!include nfUtils.nsh

!define TMP_POOLS_FILE 10
!define COLUMN_POOL_ID 20
!define COLUMN_POOL_NAME 30

!macro GetMatchInFile Un1 Un2
${nfu.Function} ${Un2}GetMatchInFile out $9 in $0 in $1 in $2 in $4 '' '' '' '' '' '' '' '' '' ''
!verbose push
!verbose 4 ; show my code
; you may use TMP_POOLS_FILE,COLUMN_POOL_ID,P_ID,COLUMN_POOL_NAME in $0,$1,$2,$4,
; collect result in $9
; your code, push and pop whatever you want:
StrCpy $9 "Result: $0$1$2$4"
; at this point the stack should be cleared from your 'local' stack-ops
!verbose pop
${nfu.FunctionEnd}
!macroend

${nfu.!InstallFunction} "" GetMatchInFile out RetVal in TmpPoolsFile in ColPoolID in pID in ColPoolName '' '' '' '' '' '' '' '' '' '' 'SomeDescription'

${nfu.!AddFunction} GetMatchInFile

!macro GetPoolNameFromPoolId P_ID P_RET
${GetMatchInFile} ${P_RET} "${TMP_POOLS_FILE}" "${COLUMN_POOL_ID}" "${P_ID}" "${COLUMN_POOL_NAME}"
!macroend

Section
SectionEnd

Function .onInit
; test the function
!insertmacro GetPoolNameFromPoolId 1 $8
FunctionEnd

If there are any other poor unfortunate individuals who are having stack problems then, this was the easiest way of solving all my problems. I'm sure that it is not as efficient as it could be, but at the end of the day its just an installer. The real goodies are in the payload!

# Written by David Newcomb
!include "WinMessages.nsh"

Name "Store test"
OutFile "Store.exe"
ShowInstDetails show

Var answer

Function .onInit
FunctionEnd

Function StoreProt

# Place stack protection code here
System::Store /NOUNLOAD "s"

# Read parameters
Pop $0
Pop $1
Pop $2
Pop $3
Pop $4

# -= Do sums =-

# Push anser
Push "six"

# Restore stack
System::Store "l"

FunctionEnd

Section

StrCpy $0 "safe0"
StrCpy $1 "safe1"
StrCpy $2 "safe2"
StrCpy $3 "safe3"
StrCpy $4 "safe4"
StrCpy $5 "safe5"
StrCpy $6 "safe6"
StrCpy $7 "safe7"
StrCpy $8 "safe8"
StrCpy $9 "safe9"

StrCpy $R0 "safeR0"
StrCpy $R1 "safeR1"
StrCpy $R2 "safeR2"
StrCpy $R3 "safeR3"
StrCpy $R4 "safeR4"
StrCpy $R5 "safeR5"
StrCpy $R6 "safeR6"
StrCpy $R7 "safeR7"
StrCpy $R8 "safeR8"
StrCpy $R9 "safeR9"

Push "one"
Push "two"
Push "three"
Push "four"
Push "five"

Call StoreProt

Pop $answer

DetailPrint "answer=$answer"

DetailPrint "0 = $0"
DetailPrint "1 = $1"
DetailPrint "2 = $2"
DetailPrint "3 = $3"
DetailPrint "4 = $4"
DetailPrint "5 = $5"
DetailPrint "6 = $6"
DetailPrint "7 = $7"
DetailPrint "8 = $8"
DetailPrint "9 = $9"

DetailPrint "R0 = $R0"
DetailPrint "R1 = $R1"
DetailPrint "R2 = $R2"
DetailPrint "R3 = $R3"
DetailPrint "R4 = $R4"
DetailPrint "R5 = $R5"
DetailPrint "R6 = $R6"
DetailPrint "R7 = $R7"
DetailPrint "R8 = $R8"
DetailPrint "R9 = $R9"

SectionEnd


i recommend reading Pop, Push, Exch... The Stack


I did read it, and I refer you to my orginal post.
When you have a function which pushs 4, uses 3 and pops 2 you have to spend 30 minutes drawing pictures of stacks to figure out whether to Exch 4 or 5.
Next time you write a function which pushs 2, uses 2 and pops 1, you have to do it all again, but slightly differently. I feel it is a bit of a waste of time.
Or you can Store/Restore and not care.


Or you use nfUtils' macros to wrap your function - and do not care ;)