- NSIS Discussion
- Push/Pop/Exch my head is spinning!
Archive: Push/Pop/Exch my head is spinning!
davidnewcomb
6th November 2006 17:30 UTC
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?
davidnewcomb
6th November 2006 18:23 UTC
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
niteflyer
6th November 2006 19:03 UTC
Untested:
${nfu.Function} GetMatchInFile out $9 in $0 in $1 in $2 in $4 '' '' '' '' '' '' '' '' '' ''
; 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:
; ...
; at this point the stack should be cleared from your 'local' stack-ops
${nfu.FunctionEnd}
${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
kichik
6th November 2006 19:13 UTC
The System plug-in can create a private stack for your function. See System::Store usage in Examples\System.
niteflyer
7th November 2006 11:43 UTC
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
davidnewcomb
7th November 2006 12:10 UTC
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
Comm@nder21
7th November 2006 19:50 UTC
i recommend reading Pop, Push, Exch... The Stack
davidnewcomb
8th November 2006 13:40 UTC
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.
niteflyer
8th November 2006 13:54 UTC
Or you use nfUtils' macros to wrap your function - and do not care ;)