Here are two routines that can be used to implement stack-based subroutines. One register will be needed to point to the call routine, and another to the ret routine. Register RF is used by both routines for temporary storage. Both routines assume R[2] is pointing to a stack.
Due to the short branches in each routine, each routine must not cross page boundaries.
1 0000: ; ***************************************************** 2 0000: ; *** Function to implement a stack based call *** 3 0000: ; *** R5 is assumed to be the main PC *** 4 0000: ; *** R2 is assumed to be the stack pointer *** 5 0000: ; *** RF is consumed *** 6 0000: ; *** usage is: sep R4 *** 7 0000: ; *** dw call_addr *** 8 0000: ; *** Routine saves R5 values onto the stack *** 9 0000: ; *** and and sets it to the call address *** 10 0000: ; ***************************************************** 11 0000: d5 sep r5 ; jump to called routine 12 0001: bf call: phi rf ; save D 13 0002: e2 sex r2 ; set x to stack segment 14 0003: 45 lda r5 ; get high byte 15 0004: af plo rf ; save it 16 0005: 15 inc r5 ; move past low address 17 0006: 85 glo r5 ; get low of return address 18 0007: 73 stxd ; store onto stack 19 0008: 95 ghi r5 ; get high of return address 20 0009: 73 stxd ; and place onto stack 21 000a: 25 dec r5 ; point to low byte 22 000b: 05 ldn r5 ; get low byte 23 000c: a5 plo r5 ; place into low byte of PC 24 000d: 8f glo rf ; recover high byte 25 000e: b5 phi r5 ; put into high of PC 26 000f: 9f ghi rf ; recover D 27 0010: 30 00 br call-1 ; transfer control 28 0012: 29 0012: d5 sep r5 ; transfer control back 30 0013: bf ret: phi rf ; save return value 31 0014: 12 inc r2 ; high byte of return address 32 0015: 42 lda r2 ; get high byte 33 0016: b5 phi r5 ; put into register 5 34 0017: 02 ldn r2 ; get low byte 35 0018: a5 plo r5 ; put into low 36 0019: 9f ghi rf ; recall return value 37 001a: 30 12 br ret-1 ; and return to caller
Lines | Description | |
---|---|---|
11 | This transfers control back to R5, leaving the Call Register again pointing to the beginning of the call routine | |
12 | This saves the value in D so that it can be used as a passed parameter to subroutines | |
13 | X is set so that we can use the STXD commands to save the return address on the stack | |
14-16 | This block moves the original PC (R5) past the call address, we pick up the high byte of the call address and store it in RF.0 on our way past | |
17-20 | This block takes the new position of R5 and stores it on the stack | |
21-23 | This block of code moves back to the low byte of the call address, retreives it and places it into R5.0 | |
24-25 | Now we retrieve the strored high address value and place it into R5.1. R5 is now pointing at the subroutine to be called | |
26-27 | Retreive the stored value of D and jump to line 11 in order to transfer control to the called subroutine |
Lines | Description | |
---|---|---|
29 | This transfers control back to R5, leaving the Ret Register again pointing to the beginning of the ret routine | |
30 | Save the value of D so that it can be used as a return value | |
31-35 | Retreive the return address from the stack and place into R5 | |
36 | Recover D | |
37 | Jump to line 29 in order to transfer control back to the original |
ldi 0beh ; byte to display sep r4 ; transfer control to call routine dw disp ; address of subroutine to call ... disp: str r2 ; write value in D to the stack sex r2 ; point the X register at stored value out 4 ; write value to the hex displays dec r2 ; put stack pointer back where it was sep r7 ; transfer control to the ret routine