Using x and y registers as an address

Building your first 6502-based project? We'll help you get started here.
pistolhamster
Posts: 4
Joined: 28 Apr 2023

Re: Using x and y registers as an address

Post by pistolhamster »

This was a good read, thank you to those who gave such well explained advice.

Allow me to ask a question: Like the OP, I dabble a bit with a simple project where I need to dynamically change memory addresses.

I want to print a series of characters on the screen starting with $0400 and ending with $07e7. To do that I have written four loops Right, down, left, up.

something like this

Code: Select all

*=$1000
right:
lda #$d7 // petscii circle
sta $0400,x
inx
cpx #40 // max length of row.
bne right
That is not too hard, the X index stops at 40, but I struggle with the "down" bit

Code: Select all

ldy #0
stx $1100 
down:
lda #$d7 // petscii circle
sta $0400,x // X must increase 40 per cycle to print downwards in a line
lda $1100 //get the stored X value (should be 40 first pass)
adc #40 
sta $1101 //
ldx $1100 
iny
cpy #25 // with 25 rows this is the max
bne down

It works until x ($1100) reaches 255, then the x index flips because it has 8 bits only, and my whole little thing comes crashung down.

Could I change the routine so that I don't address $0400,x but increment the address itself that the petscii circle is stored to?
User avatar
richardc64
Posts: 58
Joined: 08 Jun 2013
Contact:

Re: Using x and y registers as an address

Post by richardc64 »

pistolhamster wrote:
It works until x ($1100) reaches 255, then the x index flips because it has 8 bits only, and my whole little thing comes crashung down.
Is that a typo or have you coined a neologism, a new word for flawed code, combining "crash" & "hung", much like hangry?
"I am endeavoring, ma'am, to create a mnemonic memory circuit... using stone knives and bearskins." -- Spock to Edith Keeler
gfoot
Posts: 871
Joined: 09 Jul 2021

Re: Using x and y registers as an address

Post by gfoot »

Typically you would store the address in two consecutive bytes of page zero, and adjust them there by doing 16-bit adds or subtracts. Then to read or write the target memory location you set X or Y to zero and use indexed indirect addressing, i.e. (zpaddr,x) or (zpaddr),y.

However you can certainly use self-modifying code instead, if your code is in RAM. Garth linked to some examples of that upthread.

The case where self-modifying code doesn't work so well is where there are two or more instructions that all need to use the same address. There are some more complex techniques to cater for that a bit but it's simpler to just use indirect indexed addressing.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Using x and y registers as an address

Post by GARTHWILSON »

gfoot wrote:
Then to read or write the target memory location you set X or Y to zero and use indexed indirect addressing, i.e. (zpaddr,x) or (zpaddr),y.
On the 65c02, you can also do it without indexing, with:  ADC (ZP),  AND (ZP),  CMP (ZP),  EOR (ZP),  LDA (ZP),  ORA (ZP),  SBC (ZP),  and  STA (ZP).
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
pistolhamster
Posts: 4
Joined: 28 Apr 2023

Re: Using x and y registers as an address

Post by pistolhamster »

richardc64 wrote:
pistolhamster wrote:
It works until x ($1100) reaches 255, then the x index flips because it has 8 bits only, and my whole little thing comes crashung down.
Is that a typo or have you coined a neologism, a new word for flawed code, combining "crash" & "hung", much like hangry?
It would be an excellent example of serendipity. Alas, it was a typo. But yes, why not? "It crashung"
pistolhamster
Posts: 4
Joined: 28 Apr 2023

Re: Using x and y registers as an address

Post by pistolhamster »

gfoot wrote:
Typically you would store the address in two consecutive bytes of page zero, and adjust them there by doing 16-bit adds or subtracts. Then to read or write the target memory location you set X or Y to zero and use indexed indirect addressing, i.e. (zpaddr,x) or (zpaddr),y.
Thanks, you put me on the track again. This is what I managed to write and test, I now have a nice column of petscii circles.

Code: Select all

ldx #$27 
ldy #$04 
stx $60 // low byte address
sty $61 // high byte address
ldy #0 // counter
down:
    clc
    lda #81 //petscii circle
    sta ($60),y
    lda $60 // get low byte
    adc #40 // add 40 for next line
    sta $60 // store new value
    lda $61 // get high byte
    adc #0
    sta $61
    inx
    cpx #25 // max rows
    bne down
gfoot
Posts: 871
Joined: 09 Jul 2021

Re: Using x and y registers as an address

Post by gfoot »

pistolhamster wrote:
Thanks, you put me on the track again. This is what I managed to write and test, I now have a nice column of petscii circles.
Yes that's the idea. Note Garth's point that with a modern 65C02 you can also do it without using an index register.

Even on older CPUs you can also speed things up a little by swapping the roles of the Y register and the low byte of the address, i.e. $60. So you'd store zero at $60 and put the low byte of your target address into Y instead. This doesn't affect the function of the STA line, but it allows you to save a few cycles in the addition as now you can use TYA instead of LDA $60, and TAY instead of STA $60.
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Using x and y registers as an address

Post by BigDumbDinosaur »

Code: Select all

ldx #$27 
ldy #$04 
stx $60 // low byte address
sty $61 // high byte address
ldx #25 ;rows
ldy #0 // counter
down:
    lda #81 //petscii circle
    sta ($60),y
    clc
    lda $60 // get low byte
    adc #40 // add 40 for next line
    sta $60 // store new value
    lda $61 // get high byte
    adc #0
    sta $61
    dex
    bne down ;more rows
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Using x and y registers as an address

Post by barrym95838 »

gfoot wrote:
Even on older CPUs you can also speed things up a little by swapping the roles of the Y register and the low byte of the address, i.e. $60. So you'd store zero at $60 and put the low byte of your target address into Y instead. This doesn't affect the function of the STA line, but it allows you to save a few cycles in the addition as now you can use TYA instead of LDA $60, and TAY instead of STA $60.
Solid advice, every word. Shaved two bytes and ten cycles from the inner loop.

Code: Select all

    ldy #$27
    ldx #$04
    stx $61     // high byte address
    ldx #0
    stx $60     // low byte address
    ldx #25     // counter
down:
    clc
down2:
    lda #81     // petscii circle
    sta ($60),y
    dex
    beq done
    tya         // get low byte
    adc #40     // add 40 for next line
    tay         // store new value
    bcc down2
    inc $61     // update high byte
    bcs down
done:
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)
pistolhamster
Posts: 4
Joined: 28 Apr 2023

Re: Using x and y registers as an address

Post by pistolhamster »

gfoot wrote:
pistolhamster wrote:
Thanks, you put me on the track again. This is what I managed to write and test, I now have a nice column of petscii circles.
Yes that's the idea. Note Garth's point that with a modern 65C02 you can also do it without using an index register.

Even on older CPUs you can also speed things up a little by swapping the roles of the Y register and the low byte of the address, i.e. $60. So you'd store zero at $60 and put the low byte of your target address into Y instead. This doesn't affect the function of the STA line, but it allows you to save a few cycles in the addition as now you can use TYA instead of LDA $60, and TAY instead of STA $60.
Oh, that was a clever thing. Thank you.

IS the 65C02 the same as the WDC 65C02 that is still manufactured? I've seen that it will be the heart of the new Commander X16.
User avatar
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Using x and y registers as an address

Post by Dr Jefyll »

pistolhamster wrote:
IS the 65C02 the same as the WDC 65C02 that is still manufactured?
Yeah, pretty much... especially software-wise. Compared with C02's from Rockwell and CMD, for example, the current WDC product has a couple of new instructions, but they're ones you're unlikely to use -- STP and WAI. (And are you concerned about the hardware side of things? Briefly, the WDC chips can be run faster and they have some slight but important changes to the pinout; also the inputs no longer accept TTL voltage levels.)

-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
Post Reply