POKE problems by Lee Davison

Introduction

If you're thinking of using Vic BASIC, or just about any other NMOS 6502 machine with MicroSoft BASIC, for PC card I/O there is a gotcha with POKE that you need to be aware of.

Reason

On the NMOS 6502 and similar CPUs when using indirect indexed addressing a spurious read cycle is generated. This can occur at the indexed address or, if the indexing has caused an overflow into the high byte, at $100 less than the indexed address. Look at the sequence of machine cycles for the NMOS chip during an indirect indexed write.

Cycle by cycle detail for  LDA (zp),Y


cycle	type	address		description
-----	----	-------		-----------
  1	read	PC		fetch opcode, increment PC
  2	read	PC		fetch pointer address, increment PC
  3	read	pointer		fetch effective address low
  4	read	pointer+1	fetch effective address high,
				add Y to low byte of effective address		
  5	read	address+Y	read from effective address,
				fix high byte of effective address
  6	write	address+Y	write to effective address

During cycle 5 there is a spurious read from the indexed address, if this is to a sequence sensetive device such as a network card or ATA drive it can cause unpredicatble results.

Code for POKE

So how does this affect POKE, well lets take a look at the code from the Vic 20 BASIC ROM and see what happens during a POKE command.

; perform POKE

LAB_D824
	JSR	LAB_D7EB	; Get parameters for POKE/WAIT			
	TXA			; copy byte to POKE to A
	LDY	#$00		; clear index
	STA	($14),Y		; write byte
	RTS

We can see from this that POKE uses the indirect indexed addressing mode with an index of zero, so it will generate a spurious read cycle at the target address just before it writes the byte. For this reason the Vic 20 network interface code was done entirely in assembly.

The fix

The fix is to patch BASIC to use indexed indirect addressing instead of indeirect indexed. This still causes spurious read cycles but this time they are to page zero and not to the intended destination.

; perform POKE

LAB_D824
	JSR	LAB_D7EB	; Get parameters for POKE/WAIT			
	TXA			; copy byte to POKE to A
	LDX	#$00		; clear index
	STA	($14,X)		; write byte
	RTS

This is how poke is implemented in EhBASIC. This is something to remember when using either POKE in MicroSoft BASIC, or indirect indexed addressing on an NMOS 6502.


Last page update: 6th February, 2004. e-mail me