Z reg with displacement?

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

Hi there,

I made a piece of code that measures 3 different values every time, and I want to store them in the SRAM.
I'm able to store the 3 values in the SRAM once but I want to place 5 values of each in the SRAM

I know that what I'm doing is not right but it explains what I want to do. Is there a other way of doing this?

Store:		mov		temp0,count5		;counter to save sample 5 times
			cpi		temp0,$05
			brne	Store0
			clr		count5

Store0:		sbrc	Loca,0				;sample saved to tempmes1
			rjmp	Store1
			sbrc	Loca,1				;
			rjmp	Store2
			sbrc	Loca,2				;
			rjmp	Store3
			cbr		Loca,$07
			sbr		Loca,$01			
			ret

Store1:		cbr		Loca,$01			
			sbr		Loca,$02			
			ldi		Zl,low(Tempmes1)	;Set to begining of Sram
			ldi		Zh,high(Tempmes1)

			std		Z+count5,temp2		;save Sample in Sram with displacement
			ret

Store2:		cbr		Loca,$02
			sbr		Loca,$04
			ldi		Zl,low(Tempmes2)
			ldi		Zh,high(Tempmes2)

			std		Z+count5,temp2		
			ret

Store3:		inc	count5
			cbr		Loca,$04
			sbr		Loca,$01
			ldi		Zl,low(Tempmes3)
			ldi		Zh,high(Tempmes3)

			std		Z+count5,temp2		
			ret

This is what I mean:
std Z+count5,temp2
I know that on the place of count5 there must be a number, but I want this to be the number that is inside the register count5. This number is changing every time.
Can anyone give me a clue if this is possible?

Thanks,
Patrick

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

Assuming this is for a ATtiny or ATmega (not XMegas, I know nothing about those): No, it is not possible. You can get pre-decrement or post-increment, with the implied value 1. The STinstruction(s) only take two operands, the register to use as the storing address (X, Y or Z) and the register with the value to store. There is no provision to de- or increment with something other than the value 1.

When everything else fails, it is time to read the documentation :wink:. See Atmels doc0856.pdf "AVR Instruction Set", available under the documents tab on the page for your device at www.atmel.com, page 144ff. I have a hard time seeing how someone programming in assembler can do without having that document nearby as a reference during daily work.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Thu. Dec 13, 2012 - 11:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
         ldi      Zl,low(Tempmes3)
         ldi      Zh,high(Tempmes3)

         std      Z+count5,temp2      

maybe try something like:

         clr      r16
         ldi      Zl,low(Tempmes3)
         ldi      Zh,high(Tempmes3)
         add      zl, count5
         adc      zh, r16

         std      Z,temp2      

Remember that this is a RISC micro with a minimal instruction set. You have to build the "complex operations" out of the small building blocks available.

BTW I used r16 to hold 0 to add in any carry. It often makes sense to keep a register holding 0 al the time for just such a use so you don't need "clr rN"s all over the place.

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

Thanks for the quick response,

I'm using the atmega328.
And yes I have the instruction set always nearby. :wink:

@clawson,
I will try it the way you explained, but I think this will do the job. For me I don't have to look at the overflow because I will only shift 5 places and after that the count5 register will be cleared.

Thanks for your help and time,
Patrick

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

Quote:

For me I don't have to look at the overflow

But surely that depends on whether Tempmes3 is located somewhere near a 256 byte page boundary?

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

Quote:
But surely that depends on whether Tempmes3 is located somewhere near a 256 byte page boundary?

You are right :oops: I have to learn a lot thanks.

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

No RSTDISBL, no fun!

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

clawson wrote:

         ldi      Zl,low(Tempmes3)
         ldi      Zh,high(Tempmes3)

         std      Z+count5,temp2      

maybe try something like:

         clr      r16
         ldi      Zl,low(Tempmes3)
         ldi      Zh,high(Tempmes3)
         add      zl, count5
         adc      zh, r16

         st       Z,temp2      

Remember that this is a RISC micro with a minimal instruction set. You have to build the "complex operations" out of the small building blocks available.

BTW I used r16 to hold 0 to add in any carry. It often makes sense to keep a register holding 0 al the time for just such a use so you don't need "clr rN"s all over the place.

Or maybe this way:

         mov      Zl,count5
         clr      Zh
         subi     Zl,low(-Tempmes3)
         sbci     Zl,high(-Tempmes3)

         std      Z,temp2      

Or rather make .def count5=Zl if it's just temporary ...

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

Quote:
BTW I used r16 to hold 0 to add in any carry. It often makes sense to keep a register holding 0 al the time for just such a use so you don't need "clr rN"s all over the place.

But don't waste r16-r31 for this, use r0-r15 and save the more flexible upper registers for other tasks.

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

Quote:

But don't waste r16-r31 for this, use r0-r15 and save the more flexible upper registers for other tasks.

Ay that's true but don't make the huge mistake the avr-gcc compiler did and use either R0 or R1 (it uses R1) either. Only in later AVRs did it turn out that R1:R0 would be the place to deliver the result of a MUL but at that stage the compiler was already fixed to using R1 as what it calls __zero_reg__.