Need help with an incrementing 16-bit pointer

Building your first 6502-based project? We'll help you get started here.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Need help with an incrementing 16-bit pointer

Post by BigEd »

Yep, one way or another, X must be zero.
EvilSandwich
Posts: 36
Joined: 13 Oct 2019
Location: Pennsylvania, USA

Re: Need help with an incrementing 16-bit pointer

Post by EvilSandwich »

BigEd wrote:
Yep, one way or another, X must be zero.
Welp, that seems to have worked!

Code: Select all

LDA #$01 ;Initial values
LDX #$ff
LDY #$01
STX $01 ;low byte
STY $02 ;high byte

mainloop: ;placeholder program loop
JSR counter ;increment pointer
LDX #$00
LDA #$01 ;define floor color
STA ($01,X) ;sweep pixel
LDY $02 ;checking high byte
CPY #$05
BNE mainloop ;loop again
LDX $01 ;checking low byte
CPX #$ff
BNE mainloop ;loop again
BRK ;when value is 05ff, end


counter: ;incrementing subroutine

l_up: ;increment low byte
LDX $01
INC $01
CPX #$ff ;check if high byte needs to be incremented
BEQ h_up
RTS ;if not, return to main loop

h_up: ;increment high byte and return to main loop
INC $02
RTS
I still think I should get that book that Garth recommended. Because if this exercise has proven anything, it's that I REALLY need to brush up on how addressing modes work. If only so I'll stop trying to use addressing modes that don't exist. lol
EvilSandwich
Posts: 36
Joined: 13 Oct 2019
Location: Pennsylvania, USA

Re: Need help with an incrementing 16-bit pointer

Post by EvilSandwich »

drogon wrote:
Tackling the original scenario, break it down, so the increment:

Code: Select all

; inc16:
;       Add 1 to a 16-bit pointer in zero page

inc16:
        inc     ptr
        bne     :+
        inc     ptr+1
:       rts
So what you're saying here is that BNE and BEQ also have a kind of dual function as hypothetical Branch if Zero Flag Clear and Branch If Zero Flag Set opcodes if I ever need that?

Neat!
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Need help with an incrementing 16-bit pointer

Post by GARTHWILSON »

That's exactly what they do. Some instructions have been given alias names, like BLT (branch if less than) for BMI, etc.. The programming manuals will tell you that BEQ's function is to branch if the Z flag is set, and BNE's is to branch if Z is clear. (If you do a comparison and the two things are equal, the subtraction will result in 0, setting the Z flag, even if the numerical result is not kept, as in CMP, CPX, and CPY.) An automatic compare-to-zero instruction is built into the following 65c02 instructions: LDA, LDX, LDY, INC, INX, INY, DEC, DEX, DEY, INA, DEA, AND, ORA, EOR, ASL, LSR, ROL, ROR, PLA, PLX, PLY, SBC, ADC, TAX, TXA, TAY, TYA, and TSX.
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?
EvilSandwich
Posts: 36
Joined: 13 Oct 2019
Location: Pennsylvania, USA

Re: Need help with an incrementing 16-bit pointer

Post by EvilSandwich »

So really all the compare opcodes do is to kind of force a zero or non zero value to trip the Zero flag to go the way you want?
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Need help with an incrementing 16-bit pointer

Post by drogon »

EvilSandwich wrote:
So really all the compare opcodes do is to kind of force a zero or non zero value to trip the Zero flag to go the way you want?
Think of compare like a subtract operation (for that's what is really is), but with the result thrown away.

It's more useful to compare with a value, then you can branch equal (zero flag), greater than or less than.

See here: http://6502.org/tutorials/compare_instructions.html

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Need help with an incrementing 16-bit pointer

Post by GARTHWILSON »

EvilSandwich wrote:
So really all the compare opcodes do is to kind of force a zero or non zero value to trip the Zero flag to go the way you want?
They affect the relevant flags, including N and C, not just Z. BIT also affects the V flag; so for example BIT <port> (like to test an input port), will make the V flag take on the value of bit 6 of the port, regardless of what was in the accumulator. Then there's TSB (test and set bit against accumulator) and TRB (test and reset bit against accumulator) which also affect Z. TRB and TSB are read-modify-write instructions. (It's all laid out very clearly in the programming manual recommended earlier.)
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?
EvilSandwich
Posts: 36
Joined: 13 Oct 2019
Location: Pennsylvania, USA

Re: Need help with an incrementing 16-bit pointer

Post by EvilSandwich »

GARTHWILSON wrote:
They affect the relevant flags, including N and C, not just Z. BIT also affects the V flag; so for example BIT <port> (like to test an input port), will make the V flag take on the value of bit 6 of the port, regardless of what was in the accumulator. Then there's TSB (test and set bit against accumulator) and TRB (test and reset bit against accumulator) which also affect Z. TRB and TSB are read-modify-write instructions. (It's all laid out very clearly in the programming manual recommended earlier.)
If you're referring to the Programming the 65816 book, I already have it ordered. From a excerpts I read, it looks like a stellar resource. Thanks for the recommendation.

I've also been reading through the primers you wrote in the meantime. They're clearing up a LOT of things. Until then, thanks for putting up with all the rookie questions.

I'm starting to feel like a three year old that's always asking "What's that do?!"
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Need help with an incrementing 16-bit pointer

Post by BigEd »

EvilSandwich wrote:
I'm starting to feel like a three year old that's always asking "What's that do?!"
Not directly relevant, but there's a book and website called "But how do it know?" about the workings of computers.
EvilSandwich
Posts: 36
Joined: 13 Oct 2019
Location: Pennsylvania, USA

Re: Need help with an incrementing 16-bit pointer

Post by EvilSandwich »

Okay. Based on all the helpful feedback here, I've tried to refine my screen fill program to be as small as possible while using as few clock cycles as possible. This is as tiny and fast as I can make it for now.

Code: Select all

LDA #$01
LDX #$ff
STX $01
LDX #$01
STX $02

count:
INC $01
BNE main
INC $02

main: 
STA ($01),y
LDX $02
CPX #$05
BNE count
LDX $01
CPX #$ff
BNE count
I rearranged the code to remove the need for the JMP command and the only registers being used are the Accumulator and X, so I can take advantage of Y always equaling 0 and use Indirect Indexed Addressing instead to eliminate the need to load 0 into X every loop.

Whittled it down to 30 bytes and the second half of Main is only ever used after the high byte is equal to 05! :D
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: Need help with an incrementing 16-bit pointer

Post by floobydust »

Well, here's another baker's routine to fill a memory area from $0200 - $05FF with a byte value:

Code: Select all

; fill screen memory from $0200 - $05FF with a byte value
;
	LDA	#$02	;Get start page of $02
	STA	$02	;Store to high byte pointer
	STZ	$01	;Zero low byte pointer ($0200 start)
	LDX	#$06	;Get page limit of $06 ($0600)
;
	LDA	#$00	;Load A reg with fill byte (or any other value)
;
LOOP
	STA	($01)	;Store fill byte to fill area
	INC	$01	;Increment low byte pointer
	BNE	LOOP	;Loop back until rollover to zero
	INC	$02	;Increment high byte pointer
	CPX	$02	;Compare against page limit of $06
	BNE	LOOP	;Loop back back and start next page fill
	RTS		;Return to caller
;
23 bytes in all with an RTS, else 22 bytes without it, assuming inline code with something else. Note CMOS processor required.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Need help with an incrementing 16-bit pointer

Post by BigEd »

Nice one EvilSandwich. Be sure to initialise Y!

I think there might be another notch of improvement available. As you are counting up, and filling whole pages, INY can probably be part of an inner loop.

You may well then also find that you can BNE or BEQ (as appropriate) without needing to compare against a constant: the Z flag will already be what you want, in the inner loop.
EvilSandwich
Posts: 36
Joined: 13 Oct 2019
Location: Pennsylvania, USA

Re: Need help with an incrementing 16-bit pointer

Post by EvilSandwich »

floobydust wrote:
Well, here's another baker's routine to fill a memory area from $0200 - $05FF with a byte value:

Code: Select all

; fill screen memory from $0200 - $05FF with a byte value
;
	LDA	#$02	;Get start page of $02
	STA	$02	;Store to high byte pointer
	STZ	$01	;Zero low byte pointer ($0200 start)
	LDX	#$06	;Get page limit of $06 ($0600)
;
	LDA	#$00	;Load A reg with fill byte (or any other value)
;
LOOP
	STA	($01)	;Store fill byte to fill area
	INC	$01	;Increment low byte pointer
	BNE	LOOP	;Loop back until rollover to zero
	INC	$02	;Increment high byte pointer
	CPX	$02	;Compare against page limit of $06
	BNE	LOOP	;Loop back back and start next page fill
	RTS		;Return to caller
;
23 bytes in all with an RTS, else 22 bytes without it, assuming inline code with something else. Note CMOS processor required.
The more and more I see of the 65C02, the more I realize that I don't think there's much point in using the NMOS unless you really like using illegal opcodes. I would give my right arm to be about to set an address to 0 with a single opcode and being able to use indirect addressing for anything other than JMP opcodes lol

Its all so nice.
BigEd wrote:
Nice one EvilSandwich. Be sure to initialise Y!

I think there might be another notch of improvement available. As you are counting up, and filling whole pages, INY can probably be part of an inner loop.

You may well then also find that you can BNE or BEQ (as appropriate) without needing to compare against a constant: the Z flag will already be what you want, in the inner loop.
I took your advice and got it all the way down to 26 bytes:

Code: Select all

LDA #$01
LDX #$01
LDY #$00
STX $02
STY $01

count:
INC $02
LDX $02
CPX #$06
BNE main
BRK

main: 
STA ($01),y
INY
BNE main
BEQ count
I even shaved a little more off by initializing Y and using the 0 in Y for the indirect addressing AND setting the pointer's low byte at the same time.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Need help with an incrementing 16-bit pointer

Post by BigEd »

That's the spirit! The 65C02's extra opcodes are handy if you have them, but by no means necessary - and of course if you use only the originals, your code will run on either flavour.
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: Need help with an incrementing 16-bit pointer

Post by floobydust »

BigEd wrote:
That's the spirit! The 65C02's extra opcodes are handy if you have them, but by no means necessary - and of course if you use only the originals, your code will run on either flavour.
A very true statement, however, I decided to use nothing but the CMOS version decades ago. I still have the pair of Rockwell R65C02P2 processors I purchased back in the 80's and the original datasheet. One of those chips is still in my original Vic-20 and the other in my original 1541 diskette drive. I haven't written any NMOS specific code since then. Now that you can still get Rockwell CMOS chips at fairly cheap prices (for older hardware replacements) and new WDC chips, I can't see any reason to use the older NMOS chips. That's just my personal view of course, so all of my code since then requires the CMOS processor.
Post Reply