the 'X,Y, Z' registers

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi, avr's.......... well i cant understand how can i use the X, Y Z registers in assambler, i know that they are like 'pointers' and what i want to do is something like this pseudo-code:

ldi      Y, directionR23
ldi       whatpointsY, 0b0110101       ; Then R23=0110101
inc     Y  ;then Y points to R24

i did it in PIC asm , but here i dont get how to do it...

is thera a way to do it...

thanks a lot.
darkb-
"software is like sex, it's better when its free"
http://darkb.psychoaktive.org

Darkb..
"software is like sex, it's better when it's free"
http://darkb.psychoaktive.org

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you would do something like this...

.dseg
Data:
.byte 32

.cseg

DoSomethingWithData:
  ldi   YL, low(Data)    ; load address of Data
  ldi   YH, high(Data)
ReadByte:
  ld    r16, Y+          ; load Y into r16, then increment Y
  rcall DoSomethingWithR16
  cpi   YL, low(Data+32) ; have we read 32 bytes yet?
  brne  ReadByte         ; loop

/* John Butera */

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When reading from ROM, it's a little trickier,

With a table offset in TEMP

ldi ZL,low(table*2) ;loads ZL with the low byte of the table address multiplied by 2
ldi ZH,high(table*2);
clr temp2
add ZL,TEMP
adc ZH,TEMP2

LPM ;Puts the contents of the address (TABLE)+TEMP into R0

You have to mult by 2, because you're looking up bytes, that are stored as words.

You could now do this:

st Y+,R0
adiw ZL,1

Now you've stored it in ram using the address in the Y pointer, and also pointed both Z and Y at the next locations.

Stick this in a loop, and you can load 100 bytes fast.

Dave's Engineering Page: www.dvanhorn.org
Barcode and other AVR software contracting.
765 287 1987 dvanhorn@dvanhorn.org

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

well, im looking to make this written in C in asm

for (int i =0; i< 8; i++)
      register[i] = i+i;

so, what i hope that X, Y and Z register make is to point to the register r16 (for example) store one value, increment the X pointer, store one value, increment de X pointer and store one value.

is that posible?,
Thanks alot

Darkb..
"software is like sex, it's better when it's free"
http://darkb.psychoaktive.org

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, since all the GP registers are mapped to SRAM addresses (though I've never tried it). The address of each register directly corresponds to its "number", and you'll have to initialise your X pointer to the initial register's "address" (XH always being zero at such low addresses):

register   address
===================
r0         $00
r1         $01
r2         $02
...
r26        $1A  ; XL
r27        $1B  ; XH
r28        $1C  ; YL
r29        $1D  ; YH
r30        $1E  ; ZL
r31        $1F  ; ZH

Don't forget that the X, Y, and Z register pairs (pointers) are registers r26-r31. I have no idea what would happen if you used those registers to reference themselves, but now I'm curious... The rest of the code would be the same as what John and dvanhorn posted.

Enjoy

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yep, you can use the pointers to point to any other (other that its self) register. I have done it. After all it is just another portion of SRAM.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

well, i cant have a pointer to a SRAM address:

ldi r18, 0x38

	ldi	 ZH, 0
	ldi	 ZL, r18
loadbyte:
	lpm ; Load byte from program memory into r0
	tst r0 ; Check if we’ve reached the end of the message
	breq quit ; If so, quit
	out PORTB,r0 ; Put the character onto Port B
	;rcall one_sec_delay ; A short delay
	adiw ZL,1 ; Increase Z registers
	rjmp loadbyte
quit: 
	rjmp quit

what do you say?

Darkb..
"software is like sex, it's better when it's free"
http://darkb.psychoaktive.org

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
ldi r18, 0x38

   ldi    ZH, 0
   ldi    ZL, r18 

you need to either mov ZL, r18 or ldi ZL, 0x38

/* John Butera */

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok with

ldi    ZH, 0
mov ZL, r18

i get in ZL the value of r18, but imagine this code atached in a loop increasing the Z pointer to r18, r19, r20, etc...

it does not work

loop :
ldi    ZH, 0
mov ZL, r18
inc   ZL
rjmp loop

couse it will increment the value of ZL, not the address in SRAM.... one way is to do it manually until you finish

ldi    ZH, 0
mov ZL, r18
rcall  DosomethingwithZL
mov ZL, r19
rcall  DosomethingwithZL
...

but i want to do it in a loop, so the big question is
¿How do i increment the address that the Z pointer is pointing?

Thanks a lot, i know that i'm very newbie..

Darkb..
"software is like sex, it's better when it's free"
http://darkb.psychoaktive.org

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How do i increment the address that the Z pointer is pointing?
by using ld r?, Z+ ;load with post inc
or
ld r?, Z ;load
adiw Zl,1 ; add 1 to register pair.
Look at the instruction set for more

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

darkb,
I guess I'm confused as to what you are trying to do. I don't think you want to be using LPM at all, because you said you are trying to store data into the registers (addressed as SRAM). I guess if I had read the whole thread in the first place I would have been able to tell what you were trying to do.

To get a pointer to r18, you load 0x0012 into the X, Y, or Z register. 0x0000 to point to r0, 0x0001 to point to r1, and so on.

So to go back to your example (which I overlooked before.. sorry :oops:)...

for (int i =0; i< 8; i++)
      register[i] = i+i; 

.. would go something like this...

.def temp = r16

; load X with 0x0000 (a pointer to r0)
; XL is used as "i"
    ldi     XH, 0x00
    ldi     XL, 0x00
loop:
    mov     temp, XL    ; temp = i
    add     temp, XL    ; temp = i+i
    st      X+, r16     ; register[i] = temp; i++
    cpi     XL, 8       ; if i < 8 then
    brne    loop        ;    do it again

    nop

Edit: I'm still very confused.... let me know if I completely misunderstood everything

/* John Butera */

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Think of it as having 3 different 0x04 registers in the AVR compared to the PIC.

In the PIC, register 0x04 is your pointers address. This address is 8 bits wide. In the AVR, you get 3 of these and instead are 16 bits wide. This allows you to address more than 256 bytes of memory (as all newer AVR's have multiple k in some instances!).

So, you could say:

Set (YH:YL) = base of a memory cell (for example 0x2F would be YH=0, YL=0x2F)
and then read or write to the memory cell.

Same thing as in the PIC. You would have simply loaded 0x04 with the 0x2F and then read/wrote to register 0x00.

Does this help?

Regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Pepsi: that was exaclty what i was trying to explain! jeje. The only diference is that in your code:

.def temp = r16

; load X with 0x0000 (a pointer to r0)
; XL is used as "i"
    ldi     XH, 0x00
    ldi     XL, 0x00
loop:
    mov     temp, XL    ; temp = i
    add     temp, XL    ; temp = i+i
    st      X+, r16     ; register[i] = temp; i++
    cpi     XL, 8       ; if i < 8 then
    brne    loop        ;    do it again
 

the problem is that you are storing in only one register r16, but what i'm trying to do is to store in register r17, r18, r19 each value of (i+i).... And that is not what this code does, this example never increment the X pointer.

Am i wrong?

sorry for the missunderstud and for my english... thank a lot

Darkb..
"software is like sex, it's better when it's free"
http://darkb.psychoaktive.org

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I wrote:

.def temp = r16
...
    st      X+, r16     ; register[i] = temp; i++


... but since I used "temp" at the beginning, I should have used "temp" in the ST line.

So ..

.def temp = r16

; load X with 0x0000 (a pointer to r0)
; XL is used as "i"
    ldi     XH, 0x00
    ldi     XL, 0x00
loop:
    mov     temp, XL    ; temp = i
    add     temp, XL    ; temp = i+i
    st      X+, temp    ; register[i] = temp; i++
    cpi     XL, 8       ; if i < 8 then
    brne    loop        ;    do it again

.. would load 0, 2, 4, 6, 8, 10, 12, and 14 into r0 to r7

If you want to start at r16, you need to change the register used for "temp", the intial value of X (as SteveN pointed out), and also the value to compare XL with. Notice that I am using XL as the "i" counter, eliminating the need for another register. Also notice that "temp" can be a low register.

.def temp = r0

; load X with 0x0010 (a pointer to r16)
; XL is used as "i"
    ldi     XH, 0x00
    ldi     XL, 0x10
loop:
    mov     temp, XL    ; temp = i
    add     temp, XL    ; temp = i+i
    st      X+, temp    ; register[i] = temp; i++
    cpi     XL, 24      ; if i < 24 then
    brne    loop        ;    do it again

... would load 32, 34, 36, 38, 40, 42, 44, and 46 into r16 to r23

/* John Butera */

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

darkb wrote:
hi, avr's.......... well i cant understand how can i use the X, Y Z registers in assambler, i know that they are like 'pointers' and what i want to do is something like this pseudo-code:

ldi      Y, directionR23
ldi       whatpointsY, 0b0110101       ; Then R23=0110101
inc     Y  ;then Y points to R24

i did it in PIC asm , but here i dont get how to do it...

is thera a way to do it...

thanks a lot.
darkb-
"software is like sex, it's better when its free"
http://darkb.psychoaktive.org

Reading this again I think you wanted to:

 ldi  YH, 0x00
 ldi YL, 0x23
 ldi r16, 0x35  ; b0011 0101
st Y+, r16      ; store @Y and increment (YH:YL)

Now I don't have the register mapping infront of me so I am not sure if r23 really lives at address 0x0023.

Regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sxpilot450 wrote:
Now I don't have the register mapping infront of me so I am not sure if r23 really lives at address 0x0023.

I believe you meant address 23, or 0x0017. Your code does solve the OP's original question though... something I lost track of.

/* John Butera */

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Opps.. Brainfart.. Thanks!

Regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks a lot for your pattience and help, finally i understood.. .jeje

see you!
darkb

Darkb..
"software is like sex, it's better when it's free"
http://darkb.psychoaktive.org