Stacks.nsh

From NSIS Wiki
Jump to navigationJump to search

About

More or less this is an experiment to help me learn how to deal with the stack. It's quite limited but may be useful to someone.

Example

!include stack.nsh
 
!verbose 4
 
ShowInstDetails show
 
OutFile Test.exe
 
Section Test
 
    ## Place something onto the stack to verify at the end
        Push "First Item in Stack"
 
    ## Initialize the registers to have some values... the alphabet perhaps. ;o)
        StrCpy  $0 "A"
        StrCpy  $1 "B"
        StrCpy  $2 "C"
        StrCpy  $3 "D"
        StrCpy  $4 "E"
        StrCpy  $5 "F"
        StrCpy  $6 "G"
        StrCpy  $7 "H"
        StrCpy  $8 "I"
        StrCpy  $9 "J"
        StrCpy $R0 "K"
        StrCpy $R1 "L"
        StrCpy $R2 "M"
        StrCpy $R3 "N"
        StrCpy $R4 "O"
        StrCpy $R5 "P"
        StrCpy $R6 "Q"
        StrCpy $R7 "R"
        StrCpy $R8 "S"
        StrCpy $R9 "T"
 
    #Push the values onto the stack
        ${PushStack}5 83 84 65 67 75
        Call AscDecode
        Pop $R9
 
        DetailPrint '$$R9 = $R9'
 
        DetailPrint '$$0 = $0'
        DetailPrint '$$1 = $1'
        DetailPrint '$$2 = $2'
        DetailPrint '$$3 = $3'
        DetailPrint '$$4 = $4'
        DetailPrint '$$5 = $5'
 
    ;${DelStack} 4
SectionEnd
 
Function AscDecode
    ${ExchStack}5 $1 $2 $3 $4 $5
 
    DetailPrint '$$1 = $1' 
    DetailPrint '$$2 = $2'
    DetailPrint '$$3 = $3'
    DetailPrint '$$4 = $4'
    DetailPrint '$$5 = $5'
 
    ${PushStack}2 $6 $7
 
    IntFmt $6 "%c" $1
    StrCpy $7 $6
 
    IntFmt $6 "%c" $2
    StrCpy $7 $7$6
 
    IntFmt $6 "%c" $3
    StrCpy $7 $7$6
 
    IntFmt $6 "%c" $4
    StrCpy $7 $7$6
 
    IntFmt $6 "%c" $5
    StrCpy $7 $7$6
 
    Push $7
    ${MoveStack} 1 3
    ${PopStack}2 $6 $7
 
    ${ExchStack}6 R $1 $2 $3 $4 $5
FunctionEnd

Source

; ---------------------
;       Stack.nsh
; ---------------------
;
; Macros to assist with stack manipulation
;
 
!ifndef ___STACK__NSH___
!define ___STACK__NSH___ 
 
!include LogicLib.nsh
 
!warning "Stack.nsh is in Active Development$\nKnown Issues:$\n*  Unknown"
 
## Temporary Variables
    !define STACK_TEMP_VAR "!insertmacro _STACK_TEMP_VAR"
    !macro _STACK_TEMP_VAR _Pepper _Value
        !ifndef _STACK_TEMP_VAR_${_Pepper}
            !define _STACK_TEMP_VAR_${_Pepper}
            Var /GLOBAL STACK_TEMP_VAR_${_Pepper}
        !endif
        StrCpy $STACK_TEMP_VAR_${_Pepper} `${_Value}`
    !macroend
 
## Exch Stack Values
    !macro STACK_ExchStack_2 _a _b
        !if `${_a}${_b}` != `RR`
                            ;Stack: 1 2
            !if `${_a}` != `R`
                Exch ${_a}  ;Stack: A 1
            !endif
            !if `${_b}` != `R`
                Exch        ;Stack: 2 A
                Exch ${_b}  ;Stack: B A
                Exch
            !endif
        !endif
    !macroend
 
    !macro STACK_ExchStack_3 _a _b _c
                        ;Stack: 1 2 3                    
        !if `${_c}` != `R`
            Exch 2
            Exch ${_c}  ;Stack: A 2 3
            Exch 2      ;Stack: 3 2 A
        !endif
        !insertmacro STACK_ExchStack_2 ${_a} ${_b}
                    ;Stack: C B A
    !macroend
 
    !macro STACK_ExchStack_4 _a _b _c _d
                        ;Stack: 1 2 3 4
        !if `${_c}` != `R`
            Exch 3
            Exch ${_d}  ;Stack: A 2 3 4
            Exch 3      ;Stack: 4 2 3 A
        !endif
        !insertmacro STACK_ExchStack_3 ${_a} ${_b} ${_c}
                    ;Stack: D C B A
    !macroend
 
    !macro STACK_ExchStack_5 _a _b _c _d _e
                        ;Stack: 1 2 3 4 5
        !if `${_e}` != `R`
            Exch 4
            Exch ${_e}  ;Stack: A 2 3 4 5
            Exch 4      ;Stack: 5 2 3 4 A
        !endif
        !insertmacro STACK_ExchStack_4 ${_a} ${_b} ${_c} ${_d}
                    ;Stack: E D C B A
    !macroend
 
    !macro STACK_ExchStack_6 _a _b _c _d _e _f
                        ;Stack: R 1 2 3 4 5 6
        !if `${_f}` != `R`
            Exch 5      ;Stack: 6 2 3 4 5 1
            Exch ${_f}  ;Stack: F 2 3 4 5 1
            Exch 5      ;Stack: 1 2 3 4 5 F
        !endif
        !insertmacro STACK_ExchStack_5 ${_a} ${_b} ${_c} ${_d} ${_e}
                    ;Stack: A B C D E F
    !macroend
 
    !macro STACK_ExchStack_7 _a _b _c _d _e _f _g
                    ;Stack: 1 2 3 4 5 6 7
        !if `${_g}` != `R`
            Exch 6
            Exch ${_g}  ;Stack: A 2 3 4 5 6 7
            Exch 6      ;Stack: 7 2 3 4 5 6 A
        !endif
        !insertmacro STACK_ExchStack_6 ${_a} ${_b} ${_c} ${_d} ${_e} ${_f}
                    ;Stack: G F E D C B A
    !macroend
 
    !macro STACK_ExchStack_8 _a _b _c _d _e _f _g _h
                    ;Stack: 1 2 3 4 5 6 7 8
        !if `${_h}` != `R`
            Exch 7
            Exch ${_h}  ;Stack: A 2 3 4 5 6 7 8
            Exch 7      ;Stack: 8 2 3 4 5 6 7 A
        !endif
        !insertmacro STACK_ExchStack_7 ${_a} ${_b} ${_c} ${_d} ${_e} ${_f} ${_g}
                    ;Stack: H G F E D C B A
    !macroend
 
    !macro STACK_ExchStack_9 _a _b _c _d _e _f _g _h _i
                    ;Stack: 1 2 3 4 5 6 7 8 9
        !if `${_i}` != `R`
            Exch 8
            Exch ${_i}  ;Stack: A 2 3 4 5 6 7 8 9
            Exch 8      ;Stack: 9 2 3 4 5 6 7 8 A
        !endif
        !insertmacro STACK_ExchStack_8 ${_a} ${_b} ${_c} ${_d} ${_e} ${_f} ${_g} ${_h}
                    ;Stack: I H G F E D C B A
    !macroend
 
    !macro STACK_ExchStack_10 _a _b _c _d _e _f _g _h _i _j
                    ;Stack: 1 2 3 4 5 6 7 8 9 a
        !if `${_j}` != `R`
            Exch 9      ;Stack: a 2 3 4 5 6 7 8 9 1
            Exch ${_j}  ;Stack: J 2 3 4 5 6 7 8 9 a
            Exch 9      ;Stack: 1 2 3 4 5 6 7 8 9 J
        !endif
        !insertmacro STACK_ExchStack_9 ${_a} ${_b} ${_c} ${_d} ${_e} ${_f} ${_g} ${_h} ${_i}
                    ;Stack: A B C D E F G H I J
    !macroend
 
    !define ExchStack "!insertmacro STACK_ExchStack_"
 
## Push Stack Values
    !macro STACK_PutStack_1 _a
                    ;Stack:
        Push ${_a}  ;Stack: A
    !macroend
 
    !macro STACK_PutStack_2 _a _b
                    ;Stack:
        Push ${_b}  ;Stack: A
        Push ${_a}  ;Stack: B A
    !macroend
 
    !macro STACK_PutStack_3 _a _b _c
 
        Push ${_c}
        !insertmacro STACK_PutStack_2 ${_a} ${_b}
    !macroend
 
    !macro STACK_PutStack_4 _a _b _c _d
 
        Push ${_d}
        !insertmacro STACK_PutStack_3 ${_a} ${_b} ${_c}
    !macroend
 
    !macro STACK_PutStack_5 _a _b _c _d _e
 
        Push ${_e}
        !insertmacro STACK_PutStack_4 ${_a} ${_b} ${_c} ${_d}
    !macroend
 
    !macro STACK_PutStack_6 _a _b _c _d _e _f
 
        Push ${_f}
        !insertmacro STACK_PutStack_5 ${_a} ${_b} ${_c} ${_d} ${_e} 
    !macroend
 
    !macro STACK_PutStack_7 _a _b _c _d _e _f _g
 
        Push ${_g}
        !insertmacro STACK_PutStack_6 ${_a} ${_b} ${_c} ${_d} ${_e} ${_f}
    !macroend
 
    !macro STACK_PutStack_8 _a _b _c _d _e _f _g _h
 
        Push ${_h}
        !insertmacro STACK_PutStack_7 ${_a} ${_b} ${_c} ${_d} ${_e} ${_f} ${_g} 
    !macroend
    !macro STACK_PutStack_9 _a _b _c _d _e _f _g _h _i
 
        Push ${_i}
        !insertmacro STACK_PutStack_8 ${_a} ${_b} ${_c} ${_d} ${_e} ${_f} ${_g} ${_h}
    !macroend
 
    !macro STACK_PutStack_10 _a _b _c _d _e _f _g _h _i _j
 
        Push ${_j}
        !insertmacro STACK_PutStack_9 ${_a} ${_b} ${_c} ${_d} ${_e} ${_f} ${_g} ${_h} ${_i}
    !macroend
 
    !define PushStack "!insertmacro STACK_PutStack_"
 
## PopStack
    !macro STACK_PopStack_1 _a
        !if `${_a}` != `R`
            Pop ${_a}
        !endif
    !macroend
 
    !macro STACK_PopStack_2 _a _b
        ;Stack: A B
        !if `${_a}${_b}` != `RR`
            !if `${_a}` != `R`
                Pop ${_a}
                !if `${_b}` != `R`
                    Pop ${_b}
                !endif
            !else if `${_b}` != `R`
                Exch
                Pop ${_b}
                Exch
            !endif
        !endif
    !macroend
 
    !macro STACK_PopStack_3 _a _b _c
        !if `${_a}` != `R`
            Pop ${_a}
        !endif
        !insertmacro STACK_PopStack_2 ${_b} ${_c}
    !macroend
 
    !macro STACK_PopStack_4 _a _b _c _d
        Pop ${_a}
        !insertmacro STACK_PopStack_3 ${_b} ${_c} ${_d}
    !macroend
 
    !macro STACK_PopStack_5 _a _b _c _d _e
        Pop ${_a}
        !insertmacro STACK_PopStack_4 ${_b} ${_c} ${_d} ${_e}
    !macroend
 
    !macro STACK_PopStack_6 _a _b _c _d _e _f
        Pop ${_a}
        !insertmacro STACK_PopStack_5 ${_b} ${_c} ${_d} ${_e} ${_f}
    !macroend
 
    !macro STACK_PopStack_7 _a _b _c _d _e _f _g
        Pop ${_a}
        !insertmacro STACK_PopStack_6 ${_b} ${_c} ${_d} ${_e} ${_f} ${_g}
    !macroend
 
    !macro STACK_PopStack_8 _a _b _c _d _e _f _g _h
        Pop ${_a}
        !insertmacro STACK_PopStack_7 ${_b} ${_c} ${_d} ${_e} ${_f} ${_g} ${_h}
    !macroend
 
    !macro STACK_PopStack_9 _a _b _c _d _e _f _g _h _i
        Pop ${_a}
        !insertmacro STACK_PopStack_8 ${_b} ${_c} ${_d} ${_e} ${_f} ${_g} ${_h} ${_i}
    !macroend
 
    !macro STACK_PopStack_10 _a _b _c _d _e _f _g _h _i _j
        Pop ${_a}
        !insertmacro STACK_PopStack_9 ${_b} ${_c} ${_d} ${_e} ${_f} ${_g} ${_h} ${_i} ${_j}
    !macroend
 
    !define PopStack "!insertmacro STACK_PopStack_"
 
## Delete Stack
    !define DelStack `!insertmacro _STACK_DelStack`
    !macro _STACK_DelStack _Count
        ${STACK_TEMP_VAR} `Count` ``
        ${STACK_TEMP_VAR} `Pop`   ``
 
        ${For} $STACK_TEMP_VAR_Count 1 ${_Count}
            Pop $STACK_TEMP_VAR_Pop
        ${Next}
    !macroend
 
## Insert Stack  
    !define InsertStack "!insertmacro InsertStack"
    !macro InsertStack _n _v
 
        !if ${_n} > 21
            !error `$ {InsertStack} index is greater than maximum of 21: Index = ${_n}`
        !endif
        !if ${_n} < 1
            !error `$ {InsertStack} index is less than minimum of 1: Index = ${_n}`
        !endif
 
        Push `${_v}`
 
        !if ${_n} = 21
            Exch 20
        !endif    
        !if ${_n} >= 20
            Exch 19
        !endif
        !if ${_n} >= 19
            Exch 18
        !endif
        !if ${_n} >= 18
            Exch 17
        !endif
        !if ${_n} >= 17
            Exch 16
        !endif
        !if ${_n} >= 16
            Exch 15
        !endif
        !if ${_n} >= 15
            Exch 14
        !endif
        !if ${_n} >= 14
            Exch 13
        !endif
        !if ${_n} >= 13
            Exch 12
        !endif
        !if ${_n} >= 12
            Exch 11
        !endif
        !if ${_n} >= 11
            Exch 10
        !endif
        !if ${_n} >= 10
            Exch 9
        !endif
        !if ${_n} >= 9
            Exch 8
        !endif
        !if ${_n} >= 8
            Exch 7
        !endif
        !if ${_n} >= 7
            Exch 6
        !endif
        !if ${_n} >= 6
            Exch 5
        !endif
        !if ${_n} >= 5
            Exch 4
        !endif
        !if ${_n} >= 4
            Exch 3
        !endif
        !if ${_n} >= 3
            Exch 2
        !endif
        !if ${_n} >= 2
            Exch 1
        !endif
 
    !macroend
 
## Move Stack 
    !define MoveStack "!insertMacro STACK_MoveStack"
    !macro STACK_MoveStack _s _d
 
        ## Parameter Checks
            !if ! ${_s} > 0
                !error `MoveStack Error: Source index invalid.  Index=${_s}`
            !else if ! ${_d} > 0
                !error `MoveStack Error: Destination index invalid.  Index=${_d}`
            !else if ${_s} = ${_d}
                !error `MoveStack Error: Destination index is the same as Source Index.  Index=${_s}`
            !else if ${_s} >= 20
                !error `MoveStack Error: Source index invalid.  Index=${_s}`
            !else if ${_d} >= 20
                !error `MoveStack Error: Destination index invalid.  Index=${_d}`
            !endif
 
        ## Get offsets
            !define /math _src ${_s} - 1
            !define /math _dst ${_d} - 1
 
        ## If choose algorithm based on relative positions
            !if ${_s} > ${_d}
                /* Example 9 3
                           # 1 2 3 4 5 6 7 8 9
                    Exch 2 # 3 2 1 4 5 6 7 8 9
                    Exch 3 # 4 2 1 3 5 6 7 8 9
                    Exch 4 # 5 2 1 3 4 6 7 8 9
                    Exch 5 # 6 2 1 3 4 5 7 8 9
                    Exch 6 # 7 2 1 3 4 5 6 8 9
                    Exch 7 # 8 2 1 3 4 5 6 7 9
                    Exch 8 # 9 2 1 3 4 5 6 7 8
                    Exch 2 # 1 2 9 3 4 5 6 7 8
                */
                !if ${_d} <= 2
                    !if ${_s} >= 2
                        Exch
                    !endif
                !endif
                !if ${_d} <= 3
                    !if ${_s} >= 3
                        Exch 2
                    !endif
                !endif
                !if ${_d} <= 4
                    !if ${_s} >= 4
                        Exch 3
                    !endif
                !endif
                !if ${_d} <= 5
                    !if ${_s} >= 5
                        Exch 4
                    !endif
                !endif
                !if ${_d} <= 6
                    !if ${_s} >= 6
                        Exch 5
                    !endif
                !endif
                !if ${_d} <= 7
                    !if ${_s} >= 7
                        Exch 6
                    !endif
                !endif
                !if ${_d} <= 8
                    !if ${_s} >= 8
                        Exch 7
                    !endif
                !endif
                !if ${_d} <= 9
                    !if ${_s} >= 9
                        Exch 8
                    !endif
                !endif
                !if ${_d} <= 10
                    !if ${_s} >= 10
                        Exch 9
                    !endif
                !endif
                !if ${_d} <= 11
                    !if ${_s} >= 11
                        Exch 10
                    !endif
                !endif
                !if ${_d} <= 12
                    !if ${_s} >= 12
                        Exch 11
                    !endif
                !endif
                !if ${_d} <= 13
                    !if ${_s} >= 13
                        Exch 12
                    !endif
                !endif
                !if ${_d} <= 14
                    !if ${_s} >= 14
                        Exch 13
                    !endif
                !endif
                !if ${_d} <= 15
                    !if ${_s} >= 15
                        Exch 14
                    !endif
                !endif
                !if ${_d} <= 16
                    !if ${_s} >= 16
                        Exch 15
                    !endif
                !endif
                !if ${_d} <= 17
                    !if ${_s} >= 17
                        Exch 16
                    !endif
                !endif
                !if ${_d} <= 18
                    !if ${_s} >= 18
                        Exch 17
                    !endif
                !endif
                !if ${_d} <= 19
                    !if ${_s} >= 19
                        Exch 18
                    !endif
                !endif
                !if ${_d} <= 20
                    !if ${_s} >= 20
                        Exch 19
                    !endif
                !endif
                !if ${_dst} != 0
                    Exch ${_dst}
                !endif
            !else if ${_s} < ${_d}
                /* Example 3 9
                           # 1 2 3 4 5 6 7 8 9
                    Exch 2 # 3 2 1 4 5 6 7 8 9
                    Exch 8 # 9 2 1 4 5 6 7 8 3
 
                    Exch 7 # 8 2 1 4 5 6 7 9 3
                    Exch 6 # 7 2 1 4 5 6 8 9 3
                    Exch 5 # 6 2 1 4 5 7 8 9 3
                    Exch 4 # 5 2 1 4 6 7 8 9 3
                    Exch 3 # 4 2 1 5 6 7 8 9 3
                    Exch 2 # 1 2 4 5 6 7 8 9 3
                */    
 
                !if ! ${_s} = 1
                    Exch ${_src}
                !endif
 
                !if ${_d} >= 20
                    Exch 19
                !endif
                !if ${_s} <= 19
                    !if ${_d} >= 19
                        Exch 18
                    !endif
                !endif
                !if ${_s} <= 18
                    !if ${_d} >= 18
                        Exch 17
                    !endif
                !endif
                !if ${_s} <= 17
                    !if ${_d} >= 17
                        Exch 16
                    !endif
                !endif
                !if ${_s} <= 16
                    !if ${_d} >= 16
                        Exch 15
                    !endif
                !endif
                !if ${_s} <= 15
                    !if ${_d} >= 15
                        Exch 14
                    !endif
                !endif
                !if ${_s} <= 14
                    !if ${_d} >= 14
                        Exch 13
                    !endif
                !endif
                !if ${_s} <= 13
                    !if ${_d} >= 13
                        Exch 12
                    !endif
                !endif
                !if ${_s} <= 12
                    !if ${_d} >= 12
                        Exch 11
                    !endif
                !endif
                !if ${_s} <= 11
                    !if ${_d} >= 11
                        Exch 10
                    !endif
                !endif
                !if ${_s} <= 10
                    !if ${_d} >= 10
                        Exch 9
                    !endif
                !endif
                !if ${_s} <= 9
                    !if ${_d} >= 9
                        Exch 8
                    !endif
                !endif
                !if ${_s} <= 8
                    !if ${_d} >= 8
                        Exch 7
                    !endif
                !endif
                !if ${_s} <= 7
                    !if ${_d} >= 7
                        Exch 6
                    !endif
                !endif
                !if ${_s} <= 6
                    !if ${_d} >= 6
                        Exch 5
                    !endif
                !endif
                !if ${_s} <= 5
                    !if ${_d} >= 5
                        Exch 4
                    !endif
                !endif
                !if ${_s} <= 4
                    !if ${_d} >= 4
                        Exch 3
                    !endif
                !endif
                !if ${_s} <= 3
                    !if ${_d} >= 3
                        Exch 2
                    !endif
                !endif
                !if ${_s} <= 2
                    Exch
                !endif
            !endif
        !undef _src
        !undef _dst
    !macroend
!endif