View unanswered posts | View active topics It is currently Thu Mar 28, 2024 11:40 am



Reply to topic  [ 18 posts ]  Go to page 1, 2  Next
 Memory Addresses 
Author Message

Joined: Sat Aug 03, 2013 11:02 pm
Posts: 43
I have a program that needs to write to an address, but then increment the address, and write the next.

FF00: Some Data
FF01: Some Data
Etc.

The problem is how do i increment memory. I cant store the address in an 8-bit register as in:

LDAA #$ADDR
STAA STUFF
INCA

p.s. sorry if this is poorly written have to go in a few secs

_________________
intel 4004 countdown

:05000000DAF81C01000C
:00000001FF


Tue Jan 14, 2014 7:43 pm
Profile

Joined: Tue Dec 11, 2012 8:03 am
Posts: 285
Location: California
You'd normally use either and indexed or an indirect addressing mode. Indexing is often most efficient. In 6502 or 65816 you would have for example,

Code:
        LDX  #0
loop:   <put in the accumulator the data to store next>
        STA  base_addr,X   ; The accumulator's contents will get stored at base_addr plus X's contents.
        INX                ; Increment X so the next indexed store will go to the next address higher.
        CPX  #$40          ; Compare to how many you wanted to store.
        BNE  loop          ; If you haven't done that many yet, go back for another loop.


On the 6502, the two index registers are 8-bit-only (unlike the 65816), and if you want to do more than 256 bytes, you might choose to get the value to store and then do something like:

Code:
        STA  (indirect_addr)     ; The accumulator's value will get stored at the address pointed to by the _contents_ of indirect_addr.
        INC  indirect_addr       ; Increment low byte.
        BNE  label               ; If it carried,
        INC  indirect_addr + 1   ; then increment high byte too.
label:


then test if necessary to see if you've gone as far as you wanted to. (The '816 allows incrementing the 16-bit address with a single INC instruction, unlike the 6502.) It looks like you have 6800 or 6809 code above. I've looked at their instruction sets many times over the years but never written any programming for them, so I won't try here.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources


Wed Jan 15, 2014 1:08 am
Profile WWW

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
On the 68xx you use the 16-bit X register, I think.


Wed Jan 15, 2014 8:42 am
Profile
User avatar

Joined: Tue Jan 15, 2013 5:43 am
Posts: 189
:? OK, fasten your seatbelts. My Motorola skills are rusty but I'll give it a try! James, you've got some of the right stuff goin' on in the snippet you originally posted (above). But there's confusion between where you're writing to and what you're writing. IOW confusion between the address and the data.

Ed is right -- X will be good for holding the address. And we'll stick with accumulator A for the data. Here's the 6800 version:

Code:
;------------------------------------
;want to achieve    FF00: Some Data
;                   FF01: Some Data
;                   Etc.
;------------------------------------

LDX  #$FF00   ;the first address is established explicitly by loading X
LDAA SomeData ;get a byte of data
STAA (X)      ;store the byte to the address


INX           ;the next address is gotten simply by incrementing X
LDAA SomeData ;get a byte of data
STAA (X)      ;store the byte to the address


INX           ;the next address is gotten simply by incrementing X
LDAA SomeData ;get a byte of data
STAA (X)      ;store the byte to the address

;             (and so on...)


On 6809 it can be streamlined to use fewer instructions!
Code:
LDX  #$FF00   ;the first address is established explicitly by loading X
LDAA SomeData ;get a byte of data
STAA (X+)     ;store the byte to the address and get the next address by incrementing X


LDAA SomeData ;get a byte of data
STAA (X+)     ;store the byte to the address and get the next address by incrementing X


LDAA SomeData ;get a byte of data
STAA (X+)     ;store the byte to the address and get the next address by incrementing X

;             (and so on...)

The code is untested but should be at least close to correct! ;)
Cheers
Jeff

_________________
http://LaughtonElectronics.com


Thu Jan 16, 2014 5:14 am
Profile WWW

Joined: Tue Dec 31, 2013 2:01 am
Posts: 116
Location: Sacramento, CA, United States
As someone with 6800 experience, I can state that Jeff is correct, with the small caveat that (X) and (X+) are not standard Motorola assembler syntax; they should be replaced with ,X and ,X+ respectively (a leading zero is optional for most assemblers).

Mike


Fri Jan 17, 2014 3:54 am
Profile

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
Here's a simulation of the beginning of Jeff's program. Note that LDAA here is plucking from some chosen addresses in direct page, most likely in reality you'd be doing either a block move or a block fill:
http://visual6502.org/JSSim/expert-6800 ... 1&steps=54
Programming card at http://www.textfiles.com/programming/CARDS/6800
and programmer's model at http://www.sbprojects.com/sbasm/6800.php

Cheers
Ed


Fri Jan 17, 2014 12:21 pm
Profile

Joined: Tue Dec 31, 2013 2:01 am
Posts: 116
Location: Sacramento, CA, United States
BigEd wrote:
... most likely in reality you'd be doing either a block move or a block fill: ...

The 6800 can block fill quite efficiently, due to the full-sized X register. Block moves are far less efficient, due to the missing Y register. You are forced to load and re-load the source and destination addresses into X inside the loop, or resort to the use of the S register, which is a dangerous practice (any interrupts that hit during the move are going to lightly sprinkle corrupted bytes into the data that you're trying to move, unless you are very diligent about its use). Later 8-bit Motorola products added the Y register (6809 and siblings).

Mike

[Edit: Self-modifying code is another option for the 6800 move loop, but I am not a fan of that technique.]


Fri Jan 17, 2014 3:23 pm
Profile
User avatar

Joined: Tue Jan 15, 2013 5:43 am
Posts: 189
barrym95838 wrote:
(X) and (X+) are not standard Motorola assembler syntax; they should be replaced with ,X and ,X+ respectively
See? I told you I was rusty! ;) (Actually, I never did learn proper assembler syntax. Back in the day, I assembled 6809 machine code by hand.) Thanks for the correction, Mike!

Quote:
Self-modifying code is another option for the 6800 move loop, but I am not a fan of that technique.
I can sympathize with that, provided it's a well-informed decision being made. IOW, look at the pros & cons as with any other coding technique. The list of disadvantages is short but significant. Self-modifying code...
  • is non-reentrant
  • needs to be clearly commented
  • can't run entirely from ROM -- needs at least some RAM

We need to weigh those drawbacks against the advantages, which can be quite compelling -- such as a massive speed boost, or achieving something that's otherwise hideously clumsy or borderline impossible.

Oops, are we off-topic now??? :roll: ;)

cheers,
Jeff

_________________
http://LaughtonElectronics.com


Sun Jan 19, 2014 3:41 pm
Profile WWW

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
I can't find it now, but I'm pretty sure I read a story recently of an effort back in the day to write and debug a fast copy routine, where registers were loaded and then pushed - stack instructions being quite good value in clock cycles. So long as you use the stack pointer to point at the destination (not the source), and you have a little room at the end of the data, you can tolerate interrupts making use of the stack - they will write values which you will shortly overwrite when the interrupt routine returns.


Sun Jan 19, 2014 4:37 pm
Profile

Joined: Tue Dec 31, 2013 2:01 am
Posts: 116
Location: Sacramento, CA, United States
BigEd wrote:
I can't find it now, but I'm pretty sure ...

That sounds like an invitation for me to post some home-brewed 'test-cases' (untested) :roll:
Code:
          ; MoveUp for the 6800:  Non-interrupt-safe version.
          ; Move a block of num bytes _up_ from [source .. source + num - 1]
          ;   to the block starting at dest.
          ; source, num and dest are direct-page 16-bit memory variables, and
          ;   are preserved.  A, B and X are not preserved.
          ; ssave holds the stack pointer value, so that it can be properly
          ;   restored after the move.
          ; temp is used to calculate the ends of the blocks.
          ; IRQs are ignored for the duration of the move.
          ; Bad things will likely happen to the data if an NMI hits while
          ;   the stack pointer is being used in this manner.
          ; A portion of the source will be forever lost if the destination
          ;   block overlaps the beginning of the source block.  Avoid this
          ;   by using movedown instead.
          moveup:
:d6 51            ldab num+1
:96 50            ldaa num
:db 53            addb source+1    ;calculate initial source ptr
:99 52            adca source
:d7 57            stab temp+1
:97 56            staa temp
:de 56            ldx  temp        ;init source ptr reg
:d6 51            ldab num+1
:96 50            ldaa num
:db 55            addb dest+1      ;calculate initial destination ptr
:99 54            adca dest
:d7 57            stab temp+1
:97 56            staa temp
:9f 58            sts  ssave       ;save stack ptr
:0f               sei              ;disable interrupts
:9e 56            lds  temp        ;init destination ptr reg
:34               des
          moveup2:
:09               dex              ;update source ptr reg
:a6 00            ldaa 0,x         ;load byte from source
:36               psha             ;store it in destination
:9c 52            cpx  source      ;are we done yet?
:26 f8            bne  moveup2     ;  no:  repeat until done
:9e 58            lds  ssave       ;restore stack ptr
:0e               cli              ;enable interrupts
:39               rts

It appears that you're correct: an NMI would write just below the destination 'cursor', so it would be harmless unless you had overlapping source and destination blocks, or sensitive data just below the beginning of the destination block.

This version is safer, but much slower. Look at the difference in instruction count for the loop!
Code:
          ; MoveUp for the 6800:  Interrupt-safe version.
          ;
          moveup:
:d6 51            ldab num+1
:96 50            ldaa num
:db 53            addb source+1    ;calculate initial source ptr
:99 52            adca source
:d7 59            stab ssave+1
:97 58            staa ssave
:d6 51            ldab num+1
:96 50            ldaa num
:db 55            addb dest+1      ;calculate initial destination ptr
:99 54            adca dest
:d7 57            stab temp+1
:97 56            staa temp
          moveup2:
:de 58            ldx  ssave       ;get source ptr
:09               dex
:a6 00            ldaa 0,x         ;get byte from source
:df 58            stx  ssave       ;update source ptr
:de 56            ldx  temp        ;get destination ptr
:09               dex
:a7 00            staa 0,x         ;store byte to destination
:df 56            stx  temp        ;update destination ptr
:9c 54            cpx  dest        ;are we done yet?
:26 ee            bne  moveup2     ;  no:  repeat until done
:39               rts


And now the same subroutine for the 6809:
Code:
          ; 6809 Move memory up (1 byte to 64 KB)
          ; x = source start address
          ; y = destination start address
          ; d = number of bytes to move
          ;
          moveup:
:30 8b            leax d,x         ;init source ptr
:33 ab            leau d,y         ;init destination ptr
:1f 02            tfr d,y          ;save byte count
          moveup2:
:a6 82            ldaa ,-x         ;get byte from source
:36 02            pshu a           ;store byte to destination
:31 3f            leay -1,y        ;are we done yet?
:26 f7            bne  moveup2     ;  no:  repeat until done
:39               rts

If I'm not mistaken, the 6809 just kicked the 6800's @$$!

Mike B.

[Edit: noticed a bug in the 6809 example, and attempted a fix]


Last edited by barrym95838 on Tue Apr 28, 2020 11:18 pm, edited 2 times in total.



Sun Jan 19, 2014 5:27 pm
Profile
User avatar

Joined: Tue Jan 15, 2013 5:43 am
Posts: 189
BigEd wrote:
So long as you use the stack pointer to point at the destination (not the source), and you have a little room at the end of the data, you can tolerate interrupts making use of the stack
Brilliant! -- even though obvious in hindsight. The only thing I don't like about this idea is that I didn't think of it! :evil: ;)

barrym95838 wrote:
the 6809 just kicked the 6800's @$$!
Doesn't surprise me. I'm reminded of indirect-threaded Forth NEXT -- which, on 6809, requires just two instructions! (And the direct-threaded version is just one.)

J.

_________________
http://LaughtonElectronics.com


Sun Jan 19, 2014 7:24 pm
Profile WWW

Joined: Sat Aug 03, 2013 11:02 pm
Posts: 43
Nowmy problem is that I need X to loop through a string, and write the X postiton of the string into memory

_________________
intel 4004 countdown

:05000000DAF81C01000C
:00000001FF


Tue Jan 21, 2014 2:08 pm
Profile
User avatar

Joined: Tue Jan 15, 2013 5:43 am
Posts: 189
James_Parsons wrote:
Nowmy problem is that I need X to loop through a string, and write the X postiton of the string into memory
This begins to look like a school assignment. Or perhaps you have a project of your own you'd like to tell us about. In any case, it's best if you at least make a start on the problem yourself. Hint: the previous code example might be a good place to begin -- perhaps you could modify it, I mean. :geek: Have you gotten comfortable with the previous example? In particular, be certain you understand the distinction between address and data. Good luck, and be sure to show us how you're getting along! :)

cheers
Jeff

_________________
http://LaughtonElectronics.com


Tue Jan 21, 2014 3:04 pm
Profile WWW

Joined: Tue Dec 31, 2013 2:01 am
Posts: 116
Location: Sacramento, CA, United States
James_Parsons wrote:
Nowmy problem is that I need X to loop through a string, and write the X postiton of the string into memory

It sounds like you need something akin to C's strcpy() ...

What I would do on the 6800 is reserve two volatile 16-bit direct page pointer variables, then copy until a NUL was reached. For example:
Code:
strcpy:                 ; do {
        ldx  str1
        ldaa ,x         ;    a = *(str1++);
        inx
        stx  str1
        ldx  str2
        staa ,x         ;    *(str2++) = a;
        inx
        stx  str2
        cmpa #NUL       ; /* if NUL is defined as zero, you can replace 'cmpa #NUL' with 'tsta' here */
        bne  strcpy     ; } while (a != NUL);
done:
        rts             ; return ();

Sorry, I don't have time for comments right now ... maybe I'll edit some in tonight, if I'm up to it.

The 6809 version has adequate register resources to avoid the use of direct page variables in this trivial case:
Code:
strcpy:                 ; do {
        ldaa ,x+        ;    a = *(x++);
        staa ,y+        ;    *(y++) = a;
        bne  strcpy     ; } while (a != 0);
        rts             ; return ();


Mike

[Edit: Sorry for pulling that end-around on you, Jeff (I didn't see your last post clearly before making mine). You are correct that learning is usually more rewarding with a minimum of help.]


Last edited by barrym95838 on Wed Jan 22, 2014 4:49 am, edited 1 time in total.



Tue Jan 21, 2014 4:16 pm
Profile
User avatar

Joined: Tue Jan 15, 2013 5:43 am
Posts: 189
barrym95838 wrote:
Sorry for pulling that end-around on you, Jeff
Not to worry, Mike -- I don't think you gave away the answer anyway. :) What you provided is a string move routine. James's problem is more of a search.
James_Parsons wrote:
I need X to loop through a string, and write the X postiton of the string into memory
At least, I think it's a search -- are you looping in order to search for a Null at the end of the string, James? Perhaps you're looking for a specific character within the string. (I'm purely guessing.) And where in memory should X be written? There needs to be a complete description of what you're trying to accomplish! No offense, but you seem somewhat hurried and inattentive. That's the opposite of what you'll need for success with computer coding. So get the details straight and give yourself a chance! :ugeek: Best of luck, and let us know how you're getting along.

Jeff

_________________
http://LaughtonElectronics.com


Wed Jan 22, 2014 4:47 am
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 18 posts ]  Go to page 1, 2  Next

Who is online

Users browsing this forum: No registered users and 0 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:  
cron
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software