6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 22, 2024 9:10 pm

All times are UTC




Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Fri Mar 15, 2013 4:48 pm 
Offline

Joined: Fri Mar 15, 2013 4:29 pm
Posts: 4
Hello forums, I started playing with a coding the 6502 after a long search for an assembly language to learn and it seemed like the coolest one.
I looked around a bit for how to do this but I probably just couldn't word it correctly; what I'm trying to do is fill memory locations $0200-$05ff with a certain value, doesn't matter what it is. If i had to just do something like fill locations $200-$2ff it would be easy as I could just use:

Code:
   LDA #$3 ;the value to fill the memory, in this case 3
   LDX #$0
loop:
   STA $0200,X ;$0200 gets set to $0300,$0400,$0500 in the later version of this to go 1024 instead of 256
   INX
   CPX #$0
   BNE loop
   ;end


Or something like that, you get the point, x goes from 0-ff and when it loops back it stops. Easy. But obviously this wont work when you need to go to $05ff because you'd need the x register to be at least 10 bits wide instead of 8, so what I've been doing is making it so that every time it got to the end of "loop" (as in it did it 256 times) it would increment the stored memory value of the $0200 where the instruction "STA $0200,X" was stored. This worked fine, albeit seeming a little bit sketchy.
But the problem is now that im using this code as a subroutine with an ever expanding main loop above it, the memory location of $0200 keeps changing so i have to disassemble it every time to find it again and insert it into my code manually. So my question is: Is there a better way to loop through the 1024 numbers that I need to (I assume there is) and what is it? Thank you for advance and sorry if you have to answer this alot. : /


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 15, 2013 5:56 pm 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
Take a look at Indirect Indexed addressing.

Code:
    LDA #$00
    STA $10
    LDA #$02
    STA $11
    LDA #$FF
    LDY 0
LOOP:
    STA ($10), Y
    INY
    BNE LOOP


This does what your code does, but the $0200 is store in zero page, where it can be incremented.

Code:
    LDA #$00
    STA $10
    LDA #$02
    STA $11
FILL:
    LDY #0
    LDA #$FF
LOOP:
    STA ($10), Y
    INY
    BNE LOOP
    LDA $11
    CLC
    ADC #$01
    CMP #$06
    BEQ DONE
    STA $11
    BNE FILL
DONE:     


That seems to work. Fills it up with $FF.


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 15, 2013 7:15 pm 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 679
It sounds like the address range itself is fixed? Do each page in parallel:

Code:
  lda value
  ldx #0
:  sta $0200,x
   sta $0300,x
   sta $0400,x
   sta $0500,x
   inx
  bne :-           ; no cpx necessary, as inx sets the flags based on .X




Also, labels work just as well for referring to code, not just data.
Code:
  inc loop + 2      ; increments high byte of the stored address
...
loop:
  sta $0200,x
...

but you don't need to selfmod the code when using the parallel loop.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 15, 2013 9:46 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8506
Location: Midwestern USA
Yarn! wrote:
Hello forums, I started playing with a coding the 6502 after a long search for an assembly language to learn and it seemed like the coolest one.

Welcome to our little 6502 world.

Quote:
I looked around a bit for how to do this but I probably just couldn't word it correctly; what I'm trying to do is fill memory locations $0200-$05ff with a certain value, doesn't matter what it is. If i had to just do something like fill locations $200-$2ff it would be easy as I could just use:

Code:
   LDA #$3 ;the value to fill the memory, in this case 3
   LDX #$0
loop:
   STA $0200,X ;$0200 gets set to $0300,$0400,$0500 in the later version of this to go 1024 instead of 256
   INX
   CPX #$0
   BNE loop
   ;end

Or something like that, you get the point, x goes from 0-ff and when it loops back it stops. Easy. But obviously this wont work when you need to go to $05ff because you'd need the x register to be at least 10 bits wide instead of 8, so what I've been doing is making it so that every time it got to the end of "loop" (as in it did it 256 times) it would increment the stored memory value of the $0200 where the instruction "STA $0200,X" was stored. This worked fine, albeit seeming a little bit sketchy.
But the problem is now that im using this code as a subroutine with an ever expanding main loop above it, the memory location of $0200 keeps changing so i have to disassemble it every time to find it again and insert it into my code manually. So my question is: Is there a better way to loop through the 1024 numbers that I need to (I assume there is) and what is it? Thank you for advance and sorry if you have to answer this alot. : /

White Flame's first solution (above) is the most efficient in terms of raw speed (absolute addressing uses fewer clock cycles than zero page indirect). However, use of zero page indirect addressing makes your routine adaptable to different addresses:

Code:
         sta pagectr           ;set pages to clear (1-255, 0 = 256)
         stx zpptr             ;set start address LSB
         sty zpptr+1           ;set start address MSB
         lda #$EA              ;clear value -- could be anything
         ldy #0                ;index
;
l0000010 sta (zpptr),y         ;clear
         iny
         bne l00000010         ;next location
;
         dec pagectr           ;one less page to clear
         beq l0000020          ;done
;
         inc zpptr+1           ;next page
         bne l0000010          ;more pages remaining
;
l0000020 rts                   ;done

You'd call the above with the number of pages to clear in .A and the address of the region to be cleared in .X (LSB) and .Y (MSB).

Note that any time a register or memory location is incremented or decremented, anytime an MPU register is loaded from memory or a peripheral chip register, or an inter-register transfer occurs (e.g., TAX) the MPU flags are automatically conditioned. Ditto for pulling the accumulator from the stack. So a test such as CPX #0 immediately after DEX or INX is unnecessary. Note that neither .Y or PAGECTR are explicitly tested, as the act of incrementing .Y or decrementing PAGECTR will automatically set or clear the .Z (result zero) status register flag according to what the most recent operation did.


Edit: I got distracted while writing the above code and forgot to go over it for boo-boos. Now it's correct.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Last edited by BigDumbDinosaur on Sat Mar 16, 2013 7:37 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 15, 2013 10:26 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
White Flame wrote:
It sounds like the address range itself is fixed? Do each page in parallel:

Code:
  lda value
  ldx #0
:  sta $0200,x
   sta $0300,x
   sta $0400,x
   sta $0500,x
   inx
  bne :-           ; no cpx necessary, as inx sets the flags based on .X

Good idea! In fact, you could do any number of bytes that way that is a multiple of how many STA's are in the loop, for example 964 (241x4) bytes starting at $200:
Code:
      LDA  value
      LDX  #241            ; Since the loop runs with X values of 241 down to 1 (not 0),
LOOP:    STA  $1FF, X      ; we'll decrement the operands here by 1.
         STA  $2F0, X
         STA  $3E1, X
         STA  $4D2, X
      BNE  LOOP

Quote:
Note that any time a register or memory location is incremented or decremented, anytime an MPU register is loaded from memory or a peripheral chip register, or an inter-register transfer occurs (e.g., TAX) the MPU flags are automatically conditioned. Ditto for pulling the accumulator from the stack. So a test such as CPX #0 immediately after DEX or INX is unnecessary.

I'm glad you caught that. Yes, those who haven't grown accustomed yet to all the ins and outs tend do use more instructions than necessary. There's a list of these in the "Beginning Programming Tips" page of the 6502 Primer.

Then, if I can sneak this in, the 65816 has registers that can work in 8- or 16-bit mode, so a loop controlled only by a DEX is not limited to 256 iterations. It also has a memory-move instruction that can move up to 64K in a single instruction with as few as four instructions, and there's a trick where if you put the desired fill value at one end, you can use this to copy it all the way through the range.

_________________
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?


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 15, 2013 10:51 pm 
Offline

Joined: Fri Mar 15, 2013 4:29 pm
Posts: 4
OP here, sorry for late response, calculus II exam took place between original post and this one. I'm still reading through everybody's inputted code (I can't read assembly like I can just read higher level languages at this point unfortunately) but I completely understand the indirect indexed addressing mode now, I wasn't aware previously that it would use the value as the LSB AND use the next memory slot for the HSB. I'll definitely have to read through the modes more closely as it would probably make my programming a lot easier.

Also it's become apparent i have to learn a lot more about interactions between flags and operations, something fairly new to me coming from higher level languages. I found a big chart with op's effect on status flags and ill be putting it on my off-monitor for the time being.

Thanks white flame for the faster code too, I mostly wanted to have my code "adaptable to different addresses" like BigDumbDinosaur said but ill be comparing your code to my original code to learn all the ways im being inefficient.

Also, thanks Garthwilson for the link to those guides, I took a look and think those will help alot :), and thanks to the community for so many great responses, ill be sure to contribute where I can when I learn more.


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 15, 2013 11:55 pm 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
If you picked up indirect indexed that quickly, you should learn the rest of 6502 programming very quickly. Took me awhile to learn but I was in my teens and there was no internet back then.
What puts one on a master level? You'll have to look at some other peoples' code (not mine). Luckily they pop in from time to time. :wink:

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
PostPosted: Sat Mar 16, 2013 12:04 pm 
Online
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Just to say: welcome, Yarn!
Cheers
Ed


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 19, 2013 6:51 pm 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
So the OP has to take a break posting here because of his calculus exam, and I get pulled away for a week to paint our bedroom and build a bed. Now I feel old :-).

BigDumbDinosaur wrote:
Note that any time a register or memory location is incremented or decremented, anytime an MPU register is loaded from memory or a peripheral chip register, or an inter-register transfer occurs (e.g., TAX) the MPU flags are automatically conditioned.


While we're talking about this -- I've never been sure how long the flag status persists. I've always assumed it's just until the the next load etc. instruction, but never wanted to wait too long to test the flag. Am I just being nervous?


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 19, 2013 7:11 pm 
Online
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Each flag value remains until the next instruction which sets it. So, for example, the overflow flag might remain valid for ages, because only a few instructions touch it. The zero flag, on the other hand, is set by very many.


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 20, 2013 1:39 am 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 679
I've always used the C64 Programmer's Reference Guide as my 6502 reference (yes, I know the book has some issues otherwise), but it clearly shows which flags are modified or left unmodified on each instruction. I'd hope that most references do the same.

Code:
  ASL          ASL Shift Left One Bit (Memory or Accumulator)           ASL
                   +-+-+-+-+-+-+-+-+
  Operation:  C <- |7|6|5|4|3|2|1|0| <- 0
                   +-+-+-+-+-+-+-+-+                    N Z C I D V
                                                        / / / _ _ _
                                 (Ref: 10.2)
  +----------------+-----------------------+---------+---------+----------+
  | Addressing Mode| Assembly Language Form| OP CODE |No. Bytes|No. Cycles|
  +----------------+-----------------------+---------+---------+----------+
  |  Accumulator   |   ASL A               |    0A   |    1    |    2     |
  |  Zero Page     |   ASL Oper            |    06   |    2    |    5     |
  |  Zero Page,X   |   ASL Oper,X          |    16   |    2    |    6     |
  |  Absolute      |   ASL Oper            |    0E   |    3    |    6     |
  |  Absolute, X   |   ASL Oper,X          |    1E   |    3    |    7     |
  +----------------+-----------------------+---------+---------+----------+


/ = modified, was a checkmark in the original text
_ = unmodified

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 20, 2013 9:17 am 
Offline

Joined: Sun Apr 10, 2011 8:29 am
Posts: 597
Location: Norway/Japan
White Flame wrote:
[..] but it clearly shows which flags are modified or left unmodified on each instruction. I'd hope that most references do the same.
I just ran across this online 6502 reference which also has a 'Flags Affected' field for every instruction. (Haven't seen that site before, good first impression though). Of course the good old Programming the 6502 by Zaks also has this (there's a section with one instruction per page which shows flags affected). And unrelated to 6502 - my reference book for a minicomputer also includes what flags are affected for each instruction (although sadly it doesn't always describe exactly _how_ a flag is affected.. something I noticed when I wrote an emulator!)

-Tor


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 20, 2013 3:20 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8506
Location: Midwestern USA
scotws wrote:
BigDumbDinosaur wrote:
Note that any time a register or memory location is incremented or decremented, anytime an MPU register is loaded from memory or a peripheral chip register, or an inter-register transfer occurs (e.g., TAX) the MPU flags are automatically conditioned.

While we're talking about this -- I've never been sure how long the flag status persists. I've always assumed it's just until the the next load etc. instruction, but never wanted to wait too long to test the flag. Am I just being nervous?

Status register flags persist until an operation changes them, so delayed testing is acceptable. For example, consider this loop that adds two number accumulators:

Code:
         clc
         ldx #0
         ldy #s_fac            ;accumulator size
;
l0000010 lda faca,x            ;accumulator #1
         adc facb,x            ;accumulator #2
         sta faca,x            ;sum
         inx
         dey
         bne l0000010          ;not done
;
         bcs error             ;overflow

The BCS ERROR instruction will work despite being several instructions after the ADC FACB,X instruction, as none of the intervening instructions affect the carry bit.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 20, 2013 9:02 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Tor wrote:
White Flame wrote:
[..] but it clearly shows which flags are modified or left unmodified on each instruction. I'd hope that most references do the same.
I just ran across this online 6502 reference which also has a 'Flags Affected' field for every instruction. (Haven't seen that site before, good first impression though). Of course the good old Programming the 6502 by Zaks also has this (there's a section with one instruction per page which shows flags affected). And unrelated to 6502 - my reference book for a minicomputer also includes what flags are affected for each instruction (although sadly it doesn't always describe exactly _how_ a flag is affected.. something I noticed when I wrote an emulator!)

I think the 469-page Eyes & Liechty manual that WDC has for free download at http://www.westerndesigncenter.com/wdc/ ... manual.pdf should be considered the standard. It is huge, but fairly easy reading, well organized, and complete. Chapter 18, starting on page 327, dedicates a whole page to every detail of every instruction (except what happens in each cycle-- that's in another section), including a description of how it affects the flags. Some instructions get more than one page. Pages 430-434 (part of Chapter 19) have a more brief instruction table like you'll see in many manuals which also shows which flags are affected, in a column at the right. Chapter 17, starting on page 283, graphically shows the details of what happens in every addressing mode. It covers from NMOS 6502 to CMOS 6502 to 65802/816. Just about everything you could want in the way of 65xx programmer's info is there.

_________________
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?


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 20, 2013 9:33 pm 
Online
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
There's a simple logic to which flags are affected by which operations, which is quickly internalised as you gain experience. It's one of the ways in which the 6502 is a regular machine.

Let me see if this is right, for the branchable flags N, V, Z and C:
    Anything which loads or modifies A, X or Y will set Z and N appropriately.
    Also the read-modify-write instructions set Z and N appropriately (which is to say, plain stores don't)
    The shifts and rotates set C appropriately.
    Arithmetic ops set C and V appropriately except CMP doesn't affect V.
    BIT is special(*): it loads N and V from the top bits of the value from memory, and sets Z according to the AND result.
    PLP of course sets everything it can, as does RTI.
Is that it? I'll edit to incorporate corrections.

Cheers
Ed

(*) Edit: on 65C02 and 65816 BIT also has an immediate mode, which only affects Z.
Edit: noted that I'm only covering the four branchable flags.
Edit: one concise source is http://emu-docs.org/CPU%2065xx/6502.txt
... and another is http://patpend.net/technical/6502/6502ref.html


Last edited by BigEd on Wed Mar 20, 2013 10:57 pm, edited 5 times in total.

Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 31 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: