Using x and y registers as an address

Building your first 6502-based project? We'll help you get started here.
Oman395
Posts: 1
Joined: 15 Dec 2021

Using x and y registers as an address

Post by Oman395 »

Hey, very much a noob to 6502 assembly. I'm working on something that should ideally be able to increment fully up from $4000 to $7fff, but obv 8 bit registers aren't enough. Is there any way to use both x and y registers for an address?
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Using x and y registers as an address

Post by BigEd »

Welcome! I've seen X and Y used in a convention for passing parameters, but really an address can only live in one of two places: the instruction stream, and zero page. Oh, and the stack. Three places.

So, the normal scheme is to put the address in two consecutive zero page locations, use an appropriate indirect mode to use that pointer, and then to use the INC (or DEC) operations on zero page to increment and decrement. And, because these are 8 bit operations, you increment the low byte, and then detect overflow and increment the high byte if needed.
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 »

Oman395 wrote:
Hey, very much a noob to 6502 assembly. I'm working on something that should ideally be able to increment fully up from $4000 to $7fff, but obv 8 bit registers aren't enough. Is there any way to use both x and y registers for an address?

.X and/or .Y can be used as an offset to a base address, but in themselves can't be used to form an address. As Ed noted, you need to use one of the indirect addressing modes, which involves page zero. Think of page zero as a set of (slightly slower) registers, a concept referred to as “addressable register architecture.”
x86?  We ain't got no x86.  We don't NEED no stinking x86!
teamtempest
Posts: 443
Joined: 08 Nov 2009
Location: Minnesota
Contact:

Re: Using x and y registers as an address

Post by teamtempest »

If all you want to do is count from $4000 to $7fff using just the X- and Y-registers, yes, you can do that. If you want to use one of those values to form an address you can use to read from or write to, no, there's no direct way to do that. No 6502 instruction uses the paired X- and Y-registers as an address for something the A-register is doing.

What you can do, as has been pointed out above, is put the value $4000 in a pair of consecutive zero page locations (lo-byte, hi-byte) and use it as the base address of an indirect instruction. Then you can increment that value as needed to reach higher and higher addresses. The slowest way to do that would be to increment the base address by one each time while holding X or Y constant. The faster way is to increment Y by one each time and increment the base address just once every 256 times.
DRG
Posts: 66
Joined: 19 Sep 2021

Re: Using x and y registers as an address

Post by DRG »

Something like this will store $FF in memory locations $4000 to $7FFF...

Code: Select all

; ? means the value of the memory location referenced.
; $10 holds low byte of address.
; $11 hold high byte of address.
     
         .ORG $200


         LDY #$00             ; Y = $00
         TYA                  ; A = $00
         STA $10              ; Memory location $10 = $00
         LDA #$40             ; A = $40
         STA $11              ; Memory location $11 = $40
loop1    LDA #$FF             ; A = $FF
loop2    STA ($10),Y          ; ?$11 * 256 + ?$10 + Y = A
         INY                  ; Y = Y + 1
         BNE loop2            ; Y <> 0 goto loop2
         INC $11              ; $11 = $11 + 1
         LDA $11              ; A = ?$11
         CMP #$80             ; A = $80
         BNE loop1            ; If yes goto loop1
         
         BRK                  ; End
Why can't I get this code to line up? :? <= Fixed!

Thank you, BigEd - tabs replaced by spaces and a little tinkering did it!
Last edited by DRG on Fri Dec 17, 2021 6:35 pm, edited 1 time in total.
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Using x and y registers as an address

Post by BigEd »

You need to use spaces, not tabs, I think. I usually do a lot of tweaking with the preview function - to get it right on the forum, which is what matters, and whatever it has to be in the text entry box.
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 »

DRG wrote:
Something like this will store $FF in memory locations $4000 to $7FFF...

I'd do it this way:

Code: Select all

; ? means the value of the memory location referenced.
; $10 holds low byte of address.
; $11 hold high byte of address.
;     
; Below executes in 180,813 clock cycles.
;
         .ORG $200
;
         LDA #$40             ; A = $40
         LDX #$80-$40         ; page counter (64 pages)
         LDY #$00             ; Y = $00
         STA $11              ; Memory location $11 = $40
         STY $10              ; Memory location $10 = $00
         LDA #$FF             ; A = $FF
;
loop     STA ($10),Y          ; ?$11 * 256 + ?$10 + Y = A
         INY                  ; Y = Y + 1
         BNE loop             ; Y <> 0 goto loop2
;
         INC $11              ; $11 = $11 + 1
         DEX                  ; page count = page count -1
         BNE loop             ; not done
;         
         BRK                  ; End
x86?  We ain't got no x86.  We don't NEED no stinking x86!
DRG
Posts: 66
Joined: 19 Sep 2021

Re: Using x and y registers as an address

Post by DRG »

Just checked in the 6502 Simulator and mine was 118,131 clock cycles. But, that LDA/CMP pairing of mine seemed clumsy to me.

Just goes to show the OP that there are many way to skin a cat in 6502.
plasmo
Posts: 1273
Joined: 21 Dec 2018
Location: Albuquerque NM USA

Re: Using x and y registers as an address

Post by plasmo »

I guess if you truly only want to use X and Y registers only, you can do it with self-modifying code where the base address of "STA $4000,x" is modified.

Am I banished from 6502.org forever for suggesting that? :twisted:
Bill
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Using x and y registers as an address

Post by BigEd »

I don't do it often, but I wrote some self-modifying code today...
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 »

plasmo wrote:
I guess if you truly only want to use X and Y registers only, you can do it with self-modifying code where the base address of "STA $4000,x" is modified.

Am I banished from 6502.org forever for suggesting that? :twisted:
Bill
Not at all. The more I look, the more I think there is significant capability there that most of us have been neglecting.
http://wilsonminesco.com/SelfModCode/
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?
JimBoyd
Posts: 931
Joined: 05 May 2017

Re: Using x and y registers as an address

Post by JimBoyd »

plasmo wrote:
Am I banished from 6502.org forever for suggesting that? :twisted:
Bill

Nope.
Here are some links for self modifying code in the Programming and Forth subforums.
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 »

GARTHWILSON wrote:
plasmo wrote:
I guess if you truly only want to use X and Y registers only, you can do it with self-modifying code where the base address of "STA $4000,x" is modified.

Am I banished from 6502.org forever for suggesting that? :twisted:
Bill
Not at all. The more I look, the more I think there is significant capability there that most of us have been neglecting.
http://wilsonminesco.com/SelfModCode/
I have something like that in POC V1.3's SCSI driver. During the data-in and data-out bus phases, some code is copied from ROM to low RAM and self-modification sets the target address. It runs faster than using an indirect addressing mode.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
DRG
Posts: 66
Joined: 19 Sep 2021

Re: Using x and y registers as an address

Post by DRG »

How bizarre! A self modifying code is what I actually thought of overnight having slept on it.

I thought this could actually be much closer aligned to the OP's, Oman395, original thoughts i.e. can an address "shared" between the X and Y registers be used to access memory.

In essence, the code below does what a "STA X:Y" instruction would do where X=lsb and Y=msb. The STA $1234 is just a sacrificial address to ensure the correct LDA instruction is generated by the assembler. Oh, and you couldn't run it in ROM!

Code: Select all

         ; smc = self modifying code location.
         ; -> smc + 0 = $8D (LDA absolute from non-zero page address).
         ; -> smc + 1 = lsb of absolute address.
         ; -> smc + 2 = msb of absolute address.
         ;
         ; X holds the lsb of the address.
         ; Y holds the msb of the address.
         ;
         ; Acts as a pseudo "STA X:Y" instruction.
         
         .ORG $200

         LDX #$00      ; X = $00
         LDY #$40      ; Y = $40
         LDA #$FF      ; A = $FF
     
loopy    STY smc+2     ; Overwrite the msb
loopx    STX smc+1     ; Overwrite the lsb
smc      STA $1234     ; Absolute non-zeropage     
         INX           ; X = X + 1
         BNE loopx     ; X <> 0 goto loopx
         INY           ; Y = Y + 1
         CPY #$80      ; Does Y - $80 == 0
         BNE loopy     ; If yes goto loopy
         
         BRK           ; End
It takes longer (213,637 clock cycles) but, somehow, seems more elegant (IMHO).

I also worried what the reception to self modifying code would be - glad to see nothing is ruled out. :)

Such as code that has 64 lines of STA instructions (STA $4000,Y; STA $4100,Y; STA $4200,Y ... STA $7F00,Y). Much faster (2.55 times), but takes up more memory.
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 »

Taking advantage of SMC would be something like

Code: Select all

      STZ  smc+1
      LDA  #$40
      STA  smc+2
      LDA  #$FF
     
smc:  STA  $1234     ; Absolute non-zeropage.    
      INC  smc+1     ; Incr ADL.
      BNE  smc       ; If it rolled over,
      INC  smc+2     ; then incr ADH also
      BPL  smc       ; Loop until ADH reaches $80.
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?
Post Reply