Using x and y registers as an address
Using x and y registers as an address
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?
Re: Using x and y registers as an address
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.
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.
- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Using x and y registers as an address
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
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.
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.
Re: Using x and y registers as an address
Something like this will store $FF in memory locations $4000 to $7FFF...
Why can't I get this code to line up?
<= Fixed!
Thank you, BigEd - tabs replaced by spaces and a little tinkering did it!
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
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.
Re: Using x and y registers as an address
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.
- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Using x and y registers as an address
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 ; Endx86? We ain't got no x86. We don't NEED no stinking x86!
Re: Using x and y registers as an address
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.
Just goes to show the OP that there are many way to skin a cat in 6502.
Re: Using x and y registers as an address
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?
Bill
Am I banished from 6502.org forever for suggesting that?
Bill
Re: Using x and y registers as an address
I don't do it often, but I wrote some self-modifying code today...
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Using x and y registers as an address
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?
Bill
Am I banished from 6502.org forever for suggesting that?
Bill
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?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Using x and y registers as an address
plasmo wrote:
Am I banished from 6502.org forever for suggesting that?
Bill
Bill
Nope.
Here are some links for self modifying code in the Programming and Forth subforums.
- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Using x and y registers as an address
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?
Bill
Am I banished from 6502.org forever for suggesting that?
Bill
http://wilsonminesco.com/SelfModCode/
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: Using x and y registers as an address
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!
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.
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
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.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Using x and y registers as an address
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?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?