Newbie question: accessing a 16-bit memory address
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Do you have a way to run it on the actual hardware? The NMOS processor had a few bugs and quirks but this is not one of them, and the CMOS has them all fixed; so this instruction will always operate correctly on both. I'm not familiar with either of the simulators Stella or Z26. I wonder if they both came from a common source with a bug... unless we're still missing something you or your system is doing. Just out of curiosity, see if pointer+1 still has the right value in it, or if something else put a 0 there.
- BitWise
- In Memoriam
- Posts: 996
- Joined: 02 Mar 2004
- Location: Berkshire, UK
- Contact:
wstjohn wrote:
Code: Select all
;however, after this:
LDA (pointer)
STA PF0
;PF0 contains the data from $55, not from $9955
Code: Select all
LDA (pointer)Look at your assembler listing and compare the opcode with the table here http://www.obelisk.demon.co.uk/6502/reference.html#LDA.
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
I originally tried
LDA (pointer)
but dasm wouldnt compile it saying it was an unsupported address mode.
So the code I used is:
LDY #0
LDA (pointer),Y ;which is supported
STA PF1
Here's the actual code:
Thanks again for all your help. I hope this isnt a bug in the compiler or emulator...
LDA (pointer)
but dasm wouldnt compile it saying it was an unsupported address mode.
So the code I used is:
LDY #0
LDA (pointer),Y ;which is supported
STA PF1
Here's the actual code:
Code: Select all
;------------------------------------------------
; Addressing Test
;------------------------------------------------
processor 6502
include vcs.h
include macro.h
;------------------------------------------------
; Constants and Variables
;------------------------------------------------
SEG.U variables
ORG $80
PF1_pointer .word ;the two byte pointer in ZP
Screen_PF1 = $FFAA ;the address of the actual data I want (I won't really know this at compile time in the actual program)
Screen_WrongAddress = $AA ;the address that actually gets loaded
;------------------------------------------------
; START OF ROM
;------------------------------------------------
SEG Bank0
ORG $F000 ; 4k ROM start point
;-------------------------------------------------------------------------
; Game
;------------------------------------------------
Start
CLEAN_START ; Clear RAM and Registers
lda #%10101010
sta Screen_PF1
lda #%11111111
sta Screen_WrongAddress
LDA #<Screen_PF1 ; Get Lowbyte of Address
STA PF1_pointer ; Store in pointer
LDA #>Screen_PF1 ; Get Hibyte of Address
STA PF1_pointer+1 ; Store in pointer+1
ldy #0
lda (PF1_pointer),Y ;I WANT TO LOAD $FFAA INTO A
sta PF1 ;BUT PF1 ONLY GETS $AA
;the rest is just Atari stuff...
.mainLoop
jsr VERTICAL_BLANK
jsr DRAW
jsr WAIT_V_BLANK
jsr OVERSCAN
jmp .mainLoop
;-------------------------------------------------------------------------
; SUBROUTINES
;------------------------------------------------
;***** VERTICAL_BLANK *****
VERTICAL_BLANK
lda #0
sta VBLANK
VERTICAL_SYNC
lda #41 ;41 64-cycle ticks
sta TIM64T
RTS
;***** WAIT_V_BLANK *****
WAIT_V_BLANK
.waitForVBlank
lda INTIM
bne .waitForVBlank
RTS
;***** DRAW *****
DRAW
ldx #220
.drawLine
sta WSYNC
dex
bne .drawLine
RTS
;***** OVERSCAN *****
OVERSCAN
lda #%01000010
sta VBLANK
lda #35
sta TIM64T
.waitForOverscan
lda INTIM
bne .waitForOverscan
RTS
;------------------------------------------------
; Interrupt Vectors
;------------------------------------------------
echo [*-$F000]d, " ROM bytes used"
ORG $FFFA
.word Start ; NMI
.word Start ; RESET
.word Start ; IRQ
END
The test case is confusing because $AA is both one of the values stored and
part of the address. In general it's worth putting together such tests so that
each number can come from only one possible place in the code. So here, if you change
lda #%10101010
sta Screen_PF1
to
lda #%01010101
sta Screen_PF1
you should see that
lda (PF1_pointer),Y
sets A to $55. This is what indirect addressing does: the word 'pointer' is set to
the value $FFAA (with the correct byte order) so
lda (PF1_pointer),Y loads the value of the byte at location $FFAA
(assuming Y is zero) in A. The fact that that value happened to be $AA in
your example is just a distraction.
By the way, the comment says:
;I WANT TO LOAD $FFAA INTO A
;BUT PF1 ONLY GETS $AA
The wording seems wrong: A is only 8 bits wide, but the comment reads as
though you expect to get the _value_ $FFAA into, rather than the byte stored
at $FFAA.
part of the address. In general it's worth putting together such tests so that
each number can come from only one possible place in the code. So here, if you change
lda #%10101010
sta Screen_PF1
to
lda #%01010101
sta Screen_PF1
you should see that
lda (PF1_pointer),Y
sets A to $55. This is what indirect addressing does: the word 'pointer' is set to
the value $FFAA (with the correct byte order) so
lda (PF1_pointer),Y loads the value of the byte at location $FFAA
(assuming Y is zero) in A. The fact that that value happened to be $AA in
your example is just a distraction.
By the way, the comment says:
;I WANT TO LOAD $FFAA INTO A
;BUT PF1 ONLY GETS $AA
The wording seems wrong: A is only 8 bits wide, but the comment reads as
though you expect to get the _value_ $FFAA into, rather than the byte stored
at $FFAA.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
I see gnb10 posted while I was writing this, but I'll finish anyway.
If you mean the data you pick up is AA, that's what you put in Screen_PF1, so it's working right. If the data you're reading is FF from location 00AA, then it seems like there's a bug in the simulator.
Are you set up to try it on actual hardware? Simulators are of course intended to be a tool to get you going faster and help you see exactly what's going on, but after years of talking to people on these forums (this one, plus the 6502 Yahoo forum which was basically ruined by spammers, and earlier, the Delphi forum), it seems to me that the people using simulators generally don't get as far as those not using them. I'd be happy to hear discussion on it and try to nail down the exact reasons better (I think it's the mentality), but this has been my perception. My own limited use of simulators has been rather frustrating. I've written 10,000-line applications and debugged them without a simulator, writing my own routines to examine the contents of registers and the progress of other routines in the process. I'll save that discussion for later. (I'll get off my "philosopher" podium now... <stepping down>...)
Code: Select all
CLEAN_START ; Clear RAM and Registers
lda #%10101010
sta Screen_PF1
.
.
.
ldy #0
lda (PF1_pointer),Y ;I WANT TO LOAD $FFAA INTO A
sta PF1 ;BUT PF1 ONLY GETS $AA
Are you set up to try it on actual hardware? Simulators are of course intended to be a tool to get you going faster and help you see exactly what's going on, but after years of talking to people on these forums (this one, plus the 6502 Yahoo forum which was basically ruined by spammers, and earlier, the Delphi forum), it seems to me that the people using simulators generally don't get as far as those not using them. I'd be happy to hear discussion on it and try to nail down the exact reasons better (I think it's the mentality), but this has been my perception. My own limited use of simulators has been rather frustrating. I've written 10,000-line applications and debugged them without a simulator, writing my own routines to examine the contents of registers and the progress of other routines in the process. I'll save that discussion for later. (I'll get off my "philosopher" podium now... <stepping down>...)
gnb10 wrote:
The test case is confusing because $AA is both one of the values stored and
part of the address. In general it's worth putting together such tests so that
each number can come from only one possible place in the code. So here, if you change
lda #%10101010
sta Screen_PF1
to
lda #%01010101
sta Screen_PF1
you should see that
lda (PF1_pointer),Y
sets A to $55. This is what indirect addressing does: the word 'pointer' is set to
the value $FFAA (with the correct byte order) so
lda (PF1_pointer),Y loads the value of the byte at location $FFAA
(assuming Y is zero) in A. The fact that that value happened to be $AA in
your example is just a distraction.
By the way, the comment says:
;I WANT TO LOAD $FFAA INTO A
;BUT PF1 ONLY GETS $AA
The wording seems wrong: A is only 8 bits wide, but the comment reads as
though you expect to get the _value_ $FFAA into, rather than the byte stored
at $FFAA.
part of the address. In general it's worth putting together such tests so that
each number can come from only one possible place in the code. So here, if you change
lda #%10101010
sta Screen_PF1
to
lda #%01010101
sta Screen_PF1
you should see that
lda (PF1_pointer),Y
sets A to $55. This is what indirect addressing does: the word 'pointer' is set to
the value $FFAA (with the correct byte order) so
lda (PF1_pointer),Y loads the value of the byte at location $FFAA
(assuming Y is zero) in A. The fact that that value happened to be $AA in
your example is just a distraction.
By the way, the comment says:
;I WANT TO LOAD $FFAA INTO A
;BUT PF1 ONLY GETS $AA
The wording seems wrong: A is only 8 bits wide, but the comment reads as
though you expect to get the _value_ $FFAA into, rather than the byte stored
at $FFAA.
I followed your advice on changing the data in Screen_PF1 to #$55 (01010101). However, register A still gets the value at location $AA, which is #%11111111, not the value at location $FFAA, which is #%01010101.
I'm pretty sure I'm doing what everyone has suggested, but it just isnt working the way is should. Maybe the compiler is the culprit???
Thanks again.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Quote:
Maybe the compiler is the culprit???
Garth,
I don't have access to the actual hardware yet, but I can work on that. I tried it on two different emulators with the same effect...
AHA! I tried with a third emulator, and it works the way it should!!!
I guess this teaches me a lesson about real hardware vs. emulators.
I really appreciate everyone's help!
Wes
I don't have access to the actual hardware yet, but I can work on that. I tried it on two different emulators with the same effect...
AHA! I tried with a third emulator, and it works the way it should!!!
I guess this teaches me a lesson about real hardware vs. emulators.
I really appreciate everyone's help!
Wes
Many people have the ambition to write 6502 simulators, obviously not all these attempts result in perfect products!
I personally recommend Michal Kowalski's simulator (with integrated assembler) that is much used and certainly is completly "bug free". Can be downloaded from:
http://home.pacbell.net/michal_k/6502.html
If the assembler/simulator you are using not even works for the simple construction
LDY #$00
STA (ZPADD),Y
you better put it in the trash bin!
I personally recommend Michal Kowalski's simulator (with integrated assembler) that is much used and certainly is completly "bug free". Can be downloaded from:
http://home.pacbell.net/michal_k/6502.html
If the assembler/simulator you are using not even works for the simple construction
LDY #$00
STA (ZPADD),Y
you better put it in the trash bin!
Here it is, runs perfectly on the Kowalski simulator. Note that with the Kowalski system one has to use ".BYTE" instead of ".BYT". There is no generally used standard!
Code: Select all
PF0_addr = $00 ;SOME ZERO PAGE ADDRESS, HERE $00 SELECTED
;
*=$0302 ;START OF CODE
;
;SET_POINTER PF0_addr, TitleScreen_PF0 ;Macro storing addr of TitleScreen into PFO_addr
;CODE REPLACING MACRO ABOVE FOR THE CASE THAT "addr of TitleScreen" IS "TitleScreen_PF0" = $0400
;
LDA #<TitleScreen_PF0
STA PF0_addr
LDA #>TitleScreen_PF0
STA PF0_addr+1
;
;LOOP ACCESSING THE 10 FIRST VALUES OF TABLE
;
LDY #$00
LOOP LDA (PF0_addr),Y
;
;DO SOEMETHING
;
INY
CPY #$0A
BNE LOOP
BRK
*=$0400
TitleScreen_PF0 .BYTE $00
.BYTE $01
.BYTE $02
.BYTE $03
.BYTE $04
.BYTE $05
.BYTE $06
.BYTE $07
.BYTE $08
.BYTE $09
Thanks Mats, I will try that one.
I will need to because I had tried just what you have in your example and it didnt work. If I did it manually, like this:
then it would actually get each line from the rom table. However, if I did it in a loop, it didnt work at all:
I tried this with the dasm assembler on three different emulators with the same results, so I will take your advice...
I will need to because I had tried just what you have in your example and it didnt work. If I did it manually, like this:
Code: Select all
LDX #0
LDA (ZPpointer),X
STA PF0
;do something with PF0
LDX #1
LDA (ZPpointer),X
STA PF0
;do something with PF0
LDX #2
;etcCode: Select all
LDX #0
.loop
LDA (ZPpointer),X
STA PF0
;do something with PF0
INX
CPX #9 ;or however many lines it has
BNE .loop