s887212@minyos.xx.rmit.oz.au (Stephen Riehm [Romulis]) (12/03/90)
I am trying to implement a highly recursive routine.. which requires some local variables. (ie: this routine can easily do 600 iterations.. each with 4 variables). Naturally this wont fit on the c64's stack.. so I have tried making my own (included below) which half works (the push half). has anyone experimented with this sort of thing before?? the push and pop functions need to be written as subroutines (ie called with JSR) as its a recursive group of functions which call each other. they need to be able to store both the return address of the routine calling push/pop.. and they need to be able to save some local variables.. this can be done explicitly.. here is my failed attempt.. any fixes.. or completely different solutions GLADLY accepted.. and if enough people are interested I will post the best one.... thanx in advance Stephen Riehm.. s887212@minyos.xx.rmit.oz.au - soon to be dead for christmas :-( Note: this means that replies after the 7th may not be received until the new year. --- cut here for pseudo assembly code --- push onto user stack ((fd) = stack pointer) sei /* stop interrupts from possibly corrupting stack */ ldy #$00 jsr $dec.(fd) /* lda $fd ; beq skip ; dec $fe ; skip dec $fd ; rts */ lda $var1 /* store local variables onto user stack */ sta ($fd),y jsr $dec.(fd) lda $var2 sta ($fd),y jsr $dec.(fd) lda $var3 sta ($fd),y jsr $dec.(fd) txs /* get address of calling function from stack.. inx inx inx lda $0100,x sta ($fd),y /* and push it onto the user stack... inx jsr $dec.(fd) lda $0100,x sta ($fd),y lda $fe,x /* shift calling address for this function up on sta $0100,x /* the stack..removing the hole left by the above dex lda $fe,x sta $0100,x dex txs /* reset stack pointer to the new current location cli /* interrupts are allowed again rts note this much works. (i have written test code which successfully creates a stack 4000ish bytes long..) however... pop from user stack ((fd) = stack pointer) sei ldy #$00 tsx /* create a hole to put new return address into stack inx lda $0100,x /* shift address on bottom of stack.. creating space sta $fe,x /* for address from user stack inx lda $0100,x sta $fe,x lda ($fd),y /* copy address from bottom of user stack */ sta $0100,x dex iny /* stack is volatile at the moment.. so dont to any jsrs lda ($fd),y /* this kluge is catered for later.. when the stack sta $0100,x /* should be stable again. dex dex /* skip shifted address.. leaving it actively on the stack dex txs /* reset stack pointer. stack should now be stable again * jsr $inc.(fd) /* inc $fd ; beq skip ; inc $fe ; skip rts */ * jsr $inc.(fd) /* cater for iny above ldy #$00 lda ($fd),y /* get back local variables sta $var3 * jsr $inc.(fd) lda ($fd),y sta $var2 * jsr $inc.(fd) lda ($fd),y sta $var1 * jsr $inc.(fd) cli /* interrupts are allowed again rts test routine set (fd) = $8000 /* user stack.. grows down toward $7000 set var1 = 2 /* simple iteration counter jsr recur rts recur jsr $push onto user stack dec var1 beq skip jsr recur skip jsr $pop off user stack rts ok.. the push works.. and keeps the correct values for var1 etc.. no problems.. (and doesn't have any adverse effects on the stack.. although its a bit difficult walking through the code in micromon.. it also tries to use the stack.. and gets confused ) pop doesnt work... for some reason when it returns at the end (ie after cli) it goes to the point which i have marked with '*'.. then to the next '*' and so on until it gets to the last one in pop and once again.. gets confused and goes off into no-mans land. any suggestions please???