ds.asm (2403B)
1 ;;; Copyright 2021 Gerd Beuster (gerd@frombelow.net). This is free 2 ;;; software under the GNU GPL v3 license or any later version. See 3 ;;; COPYING in the root directory for details. 4 5 ;;; ---------------------------------------------------------- 6 ;;; 7 ;;; STACK 8 ;;; 9 ;;; ---------------------------------------------------------- 10 11 ;;; Software implementation of data stack. In difference to typical 12 ;;; stack implementations, this stack grows from bottom to top, because 13 ;;; we want to access elements using indirected indexed access with 14 ;;; the stack frame pointer as base. Therefore the stack should 15 ;;; be initialized with the first unoccupied RAM address after the 16 ;;; program code. 17 ;;; 18 ;;; PULL and PUSH do not move actual stack data, they just shift 19 ;;; the stack pointer. 20 ;;; 21 ;;; Local variables on the data stack are supported by macro 22 ;;; VAR. VAR i refers to the ith byte on the stack. PARAM allows 23 ;;; to pass variables to a callee. PARAM i of the caller becomes 24 ;;; VAR i of the callee. The callee should reserve stack space 25 ;;; for both its parameters and local variables. 26 ;;; 27 ;;; Stack frames used for these calls are created/destroyed by 28 ;;; subroutines create_stack_frame and delete_stack_frame. 29 ;;; 30 ;;; CALL is like jsr with parameter passing. There addressing 31 ;;; modes are supported: immediate, zero-page, and local variables. 32 ;;; For immediate and zero page, the third parameter must be lda. 33 ;;; For local variables, the third parameter must be lda_LOCAL. 34 ;;; See sw/asm/stack_test/stack_test.asm for examles. 35 36 ds .namespace 37 38 .section zero_page 39 ;; Stack 40 ptr: .word ? 41 frame_ptr: .word ? 42 .send zero_page 43 44 .section rom 45 46 create_stack_frame: 47 .block 48 ;; Store old frame pointer on stack. 49 ;; Since our stack grows bottom to top, we write 50 ;; the data before increasing the stack pointer 51 #mem.COPY_WORD_ABSOLUTE_INDIRECT ds.frame_ptr, (ds.ptr) 52 #ds.PUSH $02 ; Store old frame pointer 53 #mem.COPY_WORD_ABSOLUTE_INDIRECT ds.ptr, ds.frame_ptr ; Set new frame pointer 54 rts 55 .bend 56 57 delete_stack_frame: 58 .block 59 #mem.COPY_WORD_ABSOLUTE_INDIRECT ds.frame_ptr, ds.ptr ; Reset stack pointer to begin of frame. 60 #ds.PULL $02 ; Move stack pointer to frame reference 61 #mem.COPY_WORD_ABSOLUTE_INDIRECT (ds.ptr), ds.frame_ptr ; Restore old frame pointer. 62 rts 63 .bend 64 65 push_a: 66 .block 67 sta (ds.ptr) 68 #ds.PUSH $01 69 rts 70 .bend 71 72 pull_a: 73 .block 74 #ds.PULL $01 75 lda (ds.ptr) 76 rts 77 .bend 78 79 .send rom 80 .endn