Variable to register, inline assembly

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

I want to the compiler do this: 

 

LDI R31 lo8(0x089B)

 

and i'm using this code to try to do that:

   volatile value = 0x089B;
   
   asm volatile(
    "LDI R30, lo8(%0)       \n\t"
   	:"=m"(value)
	);

 

but in the Disassembly appear that:

 

LDI R30,0x00

 

what it's wrong.

 

Why don't worked and how to fix it.

This topic has a solution.
Last Edited: Mon. Jun 10, 2019 - 10:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

LDI can only load values that are known at link-time or earlier. volatile is not known before run-time.
.
If you disassemble .o then symbols are not yet located and disassembled as 0x0. Anyway, your code makes no sense.
.
If you want to load (the low part of) an address then the correct constraint is "i"(&var) or "r" if var is in static storage and "r"(&var) otherwise.

avrfreaks does not support Opera. Profile inactive.

Last Edited: Sun. Jun 9, 2019 - 10:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I guess you mean LDS not LDI? But why do you need asm? A simple
.
uint8_t foo;
foo = *(volatile uint8_t *) 0x89B;
.
should LDS the location.

Last Edited: Sun. Jun 9, 2019 - 02:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 SprinterSB  I thought it would be like this, but without sure until now. Thank u! (i'm tried what you said but without success in the code)

 

 clawson - You're right! But i really need to put that information in specific register.

 

I'm tryng that, but don't work because is local variable (i think).

 

uint16_t value = 0x089B;

int main(void)
{
   uint8_t valuel = (value >> 8);

   asm volatile(
    "LDS R30, %0       \n\t"
   	:"=m"(valuel)
	);
}

I'm getting "undefined reference to `Y'"

 

How to fix that access.

Last Edited: Sun. Jun 9, 2019 - 02:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Then bind 'foo' to r31

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

If do that, (like see in you faq description).. The register will be binded to this variable for ever? Or just in this part of code? I don't want lose one register in all program...

Last Edited: Sun. Jun 9, 2019 - 04:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You really need to tell what you want, the compiler don't really like that change the 8 top registers unless you directly want to 'talk' to the compiler.

 

It sounds a bit like you want a pointer that are placed in a fixed register pair (like r3:r2), so the compile only need a movw to get it to Z. (or X) (it want to control Y) 

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

You can build with "-fixed 31" to reserve r31 but note that if you call lib code it's prebuilt and does not know this. The compiler often uses Z so may have used R31 building lib code.
.
Still intrigued to know why the var has to be register located anyway. Does a RAM access really make that much difference?

Last Edited: Sun. Jun 9, 2019 - 05:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You both are totally right, my mistake sorry.

 

In this case i'm trying to move one content (value) of my C variable to SPL register... I had do that in assembly just loading the content of RAM to a register with LDS instruction, then moving the value of register to SPL with the instruction IN (I really don't know how to do that in other way).

 

But got it with the instruction OUT. Like that:

 

asm volatile (
    "out    __SP_L__, %0   \n\t"
    ::"r"(value),
    );

 

Any of you can put some code here or more explanation about my original question? Just for future readers.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Again how is that better than plain C? If I simply write:

SPL = 0x55;

then it builds as:

	SPL = 0x55;
  26:	85 e5       	ldi	r24, 0x55	; 85
  28:	8d bf       	out	0x3d, r24	; 61

can't help wondering if you are resorting to inline asm() prematurely?

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

Note to other freaks:

 

This question is directly related to the Task Context Switching question here:

https://www.avrfreaks.net/forum/switch-context-task-and-go-back-atmega328p

therefore the answers about binding a register here do not apply.

 

What I find odd is that I only connected the two by recognising the hex number 0x089B

 

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

Dare I say it again for the umpteenth time? But this looks very like the familiar story of implementation before design. Some upfront thought about what is to be achieved would pay huge dividends at the final point of implementation rather than just throwing stuff together as each following thought occurs.

 

In design you would make decisions about whether you want some register tied to specific machine registers.

 

But in the context of an "OS" where presumably the tasks may ultimately "do anything" then the user may find such a decision quite limiting if one of the rules of use is "you can't call any function from libc" (in case it uses the bound register)

As I probably said in the other thread it's always illuminating to read the implementation notes for FreeRTOS. That bascially describes the entire process of storing task contexts in a task control block to implement a pre-emptive OS.

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

What a selfish bastard OP is please band him !!!

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

Unfortunately you're right and it will be a problem not only for me and not only for now. That's made a long time to get fixed especially for beginners .. but I think many people assume that everyone here has years and years of white beards of experience .. which is not always true. 

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

continuing what I said above..

 

"..and I who am the egoist .. spare me."