According to your code, I guess PRINTN is subroutine (function, procedure, etc.) and it's called using JSR. If so, you should mind the JSR functioning: it
- decrements SP by 4
- puts return address (beginning of the instruction following JSR) to memory by address in SP
- puts subroutine address (from JSR instruction) to PC
so, after it, all offsets beyond SP you knew shall be incremented by 4. And, yep, the value in 0(SP) is accessed as 4(SP) from the subroutine, 28(SP) shall be replaced in the same way with 32(SP), and so on. RTS does the reverse - it increments SP by 4.
Moreover, each PUSH and POP change it; if you save 2 registers on stack, after these PUSHes, all offsets are additionally incremented by 8 until corresponding POPs are executed. This is easily tracked by compilers, but more hard - by humans; that e.g. would be an additional argument why x86 invented BP in addition to SP.