help understanding data transfer

Building your first 6502-based project? We'll help you get started here.
Post Reply
andrew
Posts: 12
Joined: 26 Aug 2019

help understanding data transfer

Post by andrew »

In Programming the 6502 there is a chapter on IO techniques. Zak's shows a piece of code like this:

Code: Select all

        LDX     COUNT
WATCH   LDA     STATUS
        BPL     WATCH
        LDA     INPUT
        PHA
        DEX
        BNE     WATCH          
I feel I understand this, it "watches" STATUS, then when bit 7 is one, it transfers INPUT to the stack, decreases X, then goes back to watching STATUS.

He then discusses what would happen if the data you wanted to transfer was > 256 words and to large for the stack. To deal with this, he proposes to modify the code to this:

Code: Select all

        LDY     #0
WATCH   LDA     STATUS
        BPL     WATCH
        STA    (POINTER), Y
        INC    (POINTER)
        DEC    COUNT
        BNE     WATCH          
This I am not sure on. He is still watching the status. But then he wants to transfer the status from the accumulator to (POINTER), Y. This feels like a mistake to me. It also seems strange that he is incrementing POINTER, rather than Y.

I have been thinking about this for a while and cannot figure out his motivation here. Does anyone have any thoughts? Thanks
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: help understanding data transfer

Post by BigDumbDinosaur »

andrew wrote:
In Programming the 6502 there is a chapter on IO techniques. Zak's shows a piece of code like this:

Code: Select all

        LDX     COUNT
WATCH   LDA     STATUS
        BPL     WATCH
        LDA     INPUT
        PHA
        DEX
        BNE     WATCH          
I feel I understand this, it "watches" STATUS, then when bit 7 is one, it transfers INPUT to the stack, decreases X, then goes back to watching STATUS.

That's a stack smash just waiting to happen. If that code starts out with $FF in .X and an IRQ hits just after .X has reached $00, the stack pointer will wrap and there will be no telling what might happen. The orthodox procedure would be to store the incoming byte into a circular queue, which can be any size you want.
Quote:

Code: Select all

        LDY     #0
WATCH   LDA     STATUS
        BPL     WATCH
        STA    (POINTER), Y
        INC    (POINTER)
        DEC    COUNT
        BNE     WATCH          
INC (POINTER) is not a valid 6502 instruction. Could that be a typo perchance?
x86?  We ain't got no x86.  We don't NEED no stinking x86!
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: help understanding data transfer

Post by Chromatix »

The second routine fails to read INPUT, uses the wrong syntax for incrementing the data pointer, and doesn't seem to actually handle the more than 256 words that are advertised. A better alternative, starting with PTR and LEN as 2-byte values in zero page:

Code: Select all

readBlock:
 LDY #0
 LDX LEN+1
 BEQ readTail
bigLoop: ; whole blocks of 256 bytes first
 BIT STATUS
 BPL bigLoop
 LDA INPUT
 STA (PTR),Y
 INY
 BNE bigLoop
 INC PTR+1 ; block finished, move to next one
 DEX
 BNE bigLoop
readTail: ; small block of less than 256 bytes at end
 LDX LEN
 BEQ done
smallLoop:
 BIT STATUS
 BPL smallLoop
 LDA INPUT
 STA (PTR),Y
 INY
 DEX
 BNE smallLoop
done: ; fixup the high byte of PTR that we've been advancing
 SEC
 LDA PTR+1
 SBC LEN+1
 STA PTR+1
 RTS
You may also notice I use BIT instead of LDA. This is a good way to set the N and V flags to bits 7 and 6 of a status byte without clobbering the accumulator.

The above code is an example of a "peeled" loop, which has to repeat the implementation of the loop body in both halves of the loop. It's also common to write routines like this as nested loops, but since you then run out of registers to count and index with, you must keep at least one of them in RAM - preferably one that you only need to use in the outer loop, which is executed less often. Or you could do it as a single loop with conditional decrement of the high half of the counter (kept in RAM) and increment of the pointer. So your exercise might be to try implementing those styles yourself, using my "peeled" example for reference.
andrew
Posts: 12
Joined: 26 Aug 2019

Re: help understanding data transfer

Post by andrew »

BigDumbDinosaur wrote:
INC (POINTER) is not a valid 6502 instruction. Could that be a typo perchance?
Sorry, that was my fault. It is written as INC POINTER. I've double checked though, the rest is as it is in the book. I hadn't realised what you pointed out about the stack pointer wrapping, its something I'll keep in mind now though, thanks.
Chromatix wrote:
The above code is an example of a "peeled" loop..
Thank you for a working solution, I'll try play around with changing it to different types of loops.

Its a little worrying that his answers appear to be wrong sometimes (failing to read input, not handling >256 words, stack-smashing..) but I suppose making sure you understand his answers and why they might not work is a good way to make sure you're learning.
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: help understanding data transfer

Post by barrym95838 »

I found it online:
watchfail.JPG
The single-word comment appears to be appropriate in more ways than one.
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: help understanding data transfer

Post by BigEd »

Zaks also has his name on a book for programming the 6800 - I suspect that book came first, there was some copy-pasting, and that leads to errors. The two machines have some broad similarities but many differences. But as he owned the company which published the 6502 book, he wasn't perhaps going to be held to task by an editor.
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: help understanding data transfer

Post by floobydust »

Having some typos seems all too common, even today with modern spell checkers and such. One would think that published source code examples would at least be correct, as in they were compiled or assembled to verify they're correct. Using one's position to publish error-prone material is poor at best and very sloppy indeed.

Back in those early days, I generally bought many of the books published by OSBORNE/McGraw-Hill. Computing books in general, the CRT controller handbook and some of the books from Lance Leventhal (6502 and Z80). One of my favorites is the 6502 Assembly Language Subroutines co-authored by Winthrop Saville. I would likely recommend this one for many decent code examples that were coded and assembled to run on an Apple II, that is, they actually work.
andrew
Posts: 12
Joined: 26 Aug 2019

Re: help understanding data transfer

Post by andrew »

floobydust wrote:
Back in those early days, I generally bought many of the books published by OSBORNE/McGraw-Hill. Computing books in general, the CRT controller handbook and some of the books from Lance Leventhal (6502 and Z80). One of my favorites is the 6502 Assembly Language Subroutines co-authored by Winthrop Saville. I would likely recommend this one for many decent code examples that were coded and assembled to run on an Apple II, that is, they actually work.

I think when I finish Zaks I'll move onto one of the ones you have mentioned, thanks. In the long run I'd like to make a small NES game, but I'm enjoying working through textbooks at the moment, so I'm in no rush
Post Reply