if18@vlsi.polymtl.ca (12/06/90)
In article 1140, s887212@minyos.xx.rmit.oz.au (Stephen Riehm) wrote: >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). Actually, I don't think your routine PUSH works correctly. That's mainly because you used a TXS instruction instead of TSX ! You are filling up your user stack but your not getting the data from the computer stack... And you're modifying the STACK POINTER !! Here is your own code with some corrections and/or possible optimizations between []s: push onto user stack sei ldy #$00 jsr $dec.(fd) /* lda $fd ; beq skip ; dec $fe ; skip dec $fd ; rts */ lda $var1 ^ --> [Use BNE SKIP instead of BEQ SKIP] sta ($fd),y jsr $dec.(fd) lda $var2 sta ($fd),y jsr $dec.(fd) lda $var3 sta ($fd),y jsr $dec.(fd) [ All ok up to here... except for $dec.(fd) ] [ Change the rest...] txs TSX (not txs !) inx (inx not needed) inx ( " " " ) inx ( " " " ) lda $0100,x lda $0103,x sta ($fd),y sta ($fd),y inx (inx not needed) jsr $dec.(fd) jsr $dec.(fd) lda $0100,x lda $0104,x sta ($fd),y sta ($fd),y lda $fe,x lda $0101,x sta $0100,x sta $0103,x dex (dex not needed) lda $fe,x lda $0102,x sta $0100,x sta $0104,x dex inx (update stack ptr) txs inx cli txs rts cli rts First of all, txs moves the contents from the X register to the Stack pointer register. In your case, you want to do the opposite i.e. from the Stack ptr to the X register; you should use TSX for that. lda $fe,x (and the likes) are tricky for new programmers because they DO NOT cross the boundary between page 0 and page 1 (which is the stack, by the way). It comes back to the first address in the same page. For example, if the X register value was 3 and you used lda $fe,x ,you would have the contents of address $0001 instead of $0101 ! This only occurs when you use indexing with a ZERO PAGE instruction. If you want to cross the boundary (i.e. get $0101 in the example), you should use lda $00fe,x which is the ABSOLUTE instruction. Some assemblers compile lda $00fe,x as if it were lda $fe,x ; make sure your assembler doesn't do that. By the way, page 1 (from $0100 to $01ff) is, as I said, the stack region for the C-64. It starts from $01ff downward so in your case, you should increment the Stack ptr since you want to remove an address from the Stack (that was already ok). Another problem that you had was: > jsr $dec.(fd) /* lda $fd ; beq skip ; dec $fe ; skip dec $fd ; rts */ You should have used BNE SKIP instead of BEQ SKIP since you want to dec $fe only when the contents of the accumulator (lda $fd) is 0. Here's the second part of your code and the necessary modifications: pop from user stack sei ldy #$00 tsx [Ok up to here] [Change the rest...] inx (inx not needed) lda $0100,x lda $0101,x sta $fe,x sta $00ff,x (use ABSOLUTE mode !) inx (inx not needed) lda $0100,x lda $0102,x sta $fe,x sta $0100,x lda ($fd),y lda ($fd),y sta $0100,x sta $0102,x dex (dex not needed) iny iny lda ($fd),y lda ($fd),y sta $0100,x sta $0101,x dex (this dex is not needed anymore) dex dex dex dex txs txs (update stack ptr) jsr $inc.(fd) (not needed) jsr $inc.(fd) (not needed) ldy #$00 iny lda ($fd),y lda ($fd),y sta $var3 sta $var3 jsr $inc.(fd) iny lda ($fd),y lda ($fd),y sta $var2 sta $var2 jsr $inc.(fd) iny lda ($fd),y lda ($fd),y sta $var1 sta $var1 jsr $inc.(fd) tya cli sec rts adc $fd (Add Yreg+1 to $fd) sta $fd lda $fe (this could be optimized even more...) adc #$00 sta $fe cli rts Here again, you should have used the ABSOLUTE instruction instead of the ZERO PAGE instruction. You also had a problem with $inc.(fd): > jsr $inc.(fd) /* inc $fd ; beq skip ; inc $fe ; skip rts */ You should have used BNE SKIP instead of BEQ SKIP since you want to increment $fe only when $fd returns to 0. However, you don't need the subroutine $inc.(fd) anymore because the user stack ptr (at $fd-$fe) is updated at the end of pop. You actually save bytes if you remove the subroutine $inc.(fd) (i.e. lda $fd; BNE SKIP; inc $fe; skip rts) from your code and use the above (with adc $fd). These routines could be optimized even more (as I mentionned); however, they should work fine the way they are. I didn't have time to test these routines but they seem to be working correctly with the modifications! Good luck! -- Miguel Pedro Send mail to if18@info.polymtl.ca (NOT @vlsi.polymtl.ca !!!)