Stack preservation

Post Reply
hsilop
Posts: 70
Joined: Thu Mar 14, 2019 1:35 am
Location: Canberra, Australia

Stack preservation

Post by hsilop »

I dunno about you guys but I like my programs to be "function-like" and not leave junk on the stack, simple return the result in the X register. Here are some routines that accomplish saving and restoring of the stack and the lastX value, while returning whatever value is in the X register. Call STKPUSH at the start of your program and STKPOP just before returning. You need to call STKINIT once to setup the stack pointer. I use memory below register 19 for the stack pointer and the stack.

Hope someone finds it useful.

Code: Select all

LBL "STKINIT"
18.00001
STO 19
RTN

LBL "STKPUSH"
RDN
XEQ "PUSH"
RDN
XEQ "PUSH"
RDN
XEQ "PUSH"
RDN
LASTX
XEQ "PUSH"
RDN
RTN

LBL "STKPOP"
XEQ "POP"
STO L
RDN
XEQ "POP"
XEQ "POP"
XEQ "POP"
R^
RTN

LBL "PUSH"
STO IND 19
DSE 19
RTN

LBL "POP"
ISG 19
ENTER  ;  Never runs this line!
RCL IND 19
RTN

Steve

DM32 SN: 00316
DM41X SN: 00854
DM42 SN: 03223


HP11C, HP12C, HP15C, HP16C, HP25, HP32S, HP33C, HP41CV, HP46, HP65
User avatar
pcscote
Posts: 169
Joined: Tue May 02, 2017 12:12 pm
Location: Québec/Canada

Re: Stack preservation

Post by pcscote »

Thank you for your nice program. :)

Alternative implementation used in PPC ROM.

Source code:

Code: Select all

01 LBL "SM"    // Stack to Memory  (P.408)
02 XEQ 04
03 XEQ 04
04 XEQ 04
05 XEQ 04
06 LASTX	
07 STO IND 06
08 4
09 ST- 06
10 RTN
11 LBL 04
12 STO IND 06
13 RDN
14 1
15 ST+ 06
16 RDN
17 RTN
18 LBL "MS"    // Memory to Stack (P.336)
19 4
20 ST+ 06
21 RCL IND 06
22 SIGN
23 DSE 06
24 RCL IND 06
25 DSE 06
26 RCL IND 06
27 DSE 06
28 RCL IND 06
29 DSE 06
30 RCL IND 06
31 END
Example: Init register 06 with stack destination register (here we use the base register 10)

Code: Select all

10
STO 06
Example: Stack is saved to registers 10 to 14 but stack content is lost in the process.

Code: Select all

XEQ "SM"

Code: Select all

L: LLL  ->  R14: LLL
T: TTT  ->  R13: TTT
Z: ZZZ  ->  R12: ZZZ
Y: YYY  ->  R11: YYY
X: XXX  ->  R10: XXX
Example: Recall stack from registers 10 to 14

Code: Select all

XEQ "MS"

Code: Select all

R14: LLL  ->  L: LLL
R13: TTT  ->  T: TTT
R12: ZZZ  ->  Z: ZZZ
R11: YYY  ->  Y: YYY
R10: XXX  ->  X: XXX
[DM1x/DM1xL/DM41/DM41L/DM41X/DM42]
hsilop
Posts: 70
Joined: Thu Mar 14, 2019 1:35 am
Location: Canberra, Australia

Re: Stack preservation

Post by hsilop »

Hey - nice use of DSE, I didn't know that if cc is zero it defaults to one. Very useful. I found ISG a cleaner way to increment the stack pointer, even though it always skips the next instruction. Less overhead than 1, ST+ and all that stack rigmarole.
Steve

DM32 SN: 00316
DM41X SN: 00854
DM42 SN: 03223


HP11C, HP12C, HP15C, HP16C, HP25, HP32S, HP33C, HP41CV, HP46, HP65
dlachieze
Posts: 613
Joined: Thu May 04, 2017 12:20 pm
Location: France

Re: Stack preservation

Post by dlachieze »

hsilop wrote:
Mon Nov 09, 2020 11:35 pm
I dunno about you guys but I like my programs to be "function-like" and not leave junk on the stack, simple return the result in the X register. Here are some routines that accomplish saving and restoring of the stack and the lastX value, while returning whatever value is in the X register.
So to be "function-like" you need to save X, Y, Z and T at the beginning of your programs and restore Y, Z and T at the end while keeping in X the output of the program, and returning the initial value of X in L. No need to save the lastX value at the beginning of the program.

Here is how I would do it, based on your programs:

Code: Select all

01 LBL "STKINIT"
02 18
03 STO 19
04 RTN

05 LBL "STKPUSH"
06 XEQ "PUSH"	;Push X
07 XEQ" PUSH"	;Push Y
08 XEQ "PUSH"	;Push Z
09 XEQ" PUSH"	;Push T
10 RTN

11 LBL "STKPOP"
12 SIGN		; Save X in L
13 XEQ "POP"	; Pop T
14 XEQ" POP"	; Pop Z
15 XEQ "POP"	; Pop Y
16 XEQ" POP"	; Pop LastX
17 X<> L	; Restore X and L
18 RTN

19 LBL "PUSH"
20 STO IND 19
21 DSE 19
22 RDN
23 RTN

24 LBL "POP"
25 ISG 19
26 ENTER
27 RCL IND 19
28 END
If you don't want to disturb the stack with STKINIT you can do:

Code: Select all

01 LBL "STKINIT"
02 STO 19
03 CLx
04 18
05 X<> 19
06 RTN
DM42: 00425 - DM41X: β00066 - WP43: 00042
hth313
Posts: 46
Joined: Thu Jun 15, 2017 8:00 pm

Re: Stack preservation

Post by hth313 »

My just released Boost module contains MCODE functions to do this.

PUSHST pushes the XYZTL stack onto a dynamic stack that is maintained in a buffer in the free memory area. You can then mess up the stack as you like and leave the result in X. Then just do POPFLXL which pops back the stack (YZT), leaves X alone and moves the old X to L.

A companion routine is POPDRXL which works the same, but as if you function took two arguments (in X and Y), dropping the stack.

So your RPN function may be:

Code: Select all

PUSHST
do calculation based on X, mess up the stack
leave result in X
POPFLXL
Reference:
https://github.com/hth313/boost41/releases/tag/v0B
(see Buffer stack, page 25)
Post Reply