|
Post by VDC 8x2 on Jul 19, 2014 18:48:51 GMT
Thought of a way to pass augments to a subroutine via the stack.
start lda #$03 pha ;put 3 on stack jsr subroutine pla ;clean up stack rts
subroutine tsx lda $103,x ;we got the value sta $20 ;do something with a rts
Any other stack tricks to try?
|
|
|
Post by hydrophilic on Jul 20, 2014 1:20:39 GMT
That's pretty nice and easy. One of the most practical ways to use the stack with limitations of a 6502.
Another slightly more complicated way allows you to indirectly pass a large a number of arguments without push and pop. It is the method used by KERNAL PrImm. Just JSR to a subroutine and place all your data after the JSR.
jsr MySub .byte x1 .byte y1 .byte x2 .byte y2 lda #blue ;continue here... what ever jsr color
...
MySub: tsx lda $101,x sta $20 lda $102,x sta $21 ldy #1,2,3,4 ;access any of the 4 bytes lda ($20),y nop ;do something with it lda #4 ;#bytes on stack tsx ;index bad 'return address' clc adc $101,x ;fix return address sta $101,x bcc + inc $102,x + rts Compared to your first method, it takes about 16 cycles setup + 17 cycles of clean-up (33 overhead), while your first method takes 9 cycles setup + 4 cleanup (13 overhead). Of course this method has constant overhead, while your method would need more cycles with more arguments... I'm guessing four or more bytes and this method would be better... Well lots of other trade-offs to consider too... but something to think about.
Only other stack thing I can think of now is thread-safe exchange registers...
;swap X and Y pha tya pha txa tay pla tax pla
;swap A and X pha pha txa tsx sta $102,x pla tax pla
;swap A and Y pha pha txa pha tya tsx sta $103,x pla tax pla tay pla
|
|
|
Post by VDC 8x2 on Jul 20, 2014 12:18:09 GMT
A way to do it without clean up. I think...
start tsx dex dex dex lda #01 sta $100,x dex lda #$02 sta $100,x jsr subroutine do stuff with having to clean up
subroutine tsx lda $100,x sta somewhere dex lda $100,x sta someplace do stuff rts
|
|
|
Post by hydrophilic on Jul 20, 2014 13:03:34 GMT
I think you have too many DEX after start (3... should be 2?)
More importantly, the stuff you store at $100,x would get clobbered by an IRQ. If interrupts are impossible, then it may be useful...
Edit Also, if you're subroutine pushed any data on the stack or called a subroutine, the data stored at $100,x by the original caller would get clobbered. Of course you could save the data at $100,x before doing any push or JSR.
|
|
|
Post by VDC 8x2 on Jul 20, 2014 21:35:12 GMT
what about using the mmu to make a separate stack for parameters.
would have the sei while working with separate stack.
|
|
|
Post by hydrophilic on Jul 21, 2014 0:26:23 GMT
Sure, that is what the MMU is good for Just need to maintain a variable storing the stack pointer for your data stack. You shouldn't need to disable interrupts if properly written. But then, it is about as much work as a software stack... tsx stx cpu_stack ;save 'real' / cpu stack pointer lda #dummy ;for example $0b.... any unused memory page sta $d509 ldx data_stk ;get 'data' stack pointer txs lda #data ;for example $0c, stack for data in $c00~cff sta $d509 ;repeat as much as you want lda some_data pha ; lda #dummy sta $d509 ldx cpu_stack txs lda #1 ;the CPU stack page sta $d509 jsr subroutine
Well that is a bit verbose because it does not disable IRQs. Here is alternate version that does: tsx stx cpu_stack ;save 'real' / cpu stack pointer ldx data_stk ;get 'data' stack pointer lda #data ;for example $0c, stack for data in $c00~cff sei txs sta $d509 cli ;repeat as much as you want lda some_data pha ; ldx cpu_stack lda #1 ;the CPU stack page sei txs sta $d509 cli jsr subroutine Not shown is similar code the 'subroutine' would need to access the data stack. In summary, I don't this would be any better (probably slower) than using a software stack. I think the MMU method is better for multiple threads, because the MMU only gets updated on a task swap which happens far less frequently than calling subroutines. But maybe I am missing something?
|
|