Inline Assembler; "Impossible constraint" for byte value > 127

I'm trying to pass a byte to some inline assembly code.

0-127 works fine

127 throws an 'impossible constraint' error.

I've read some gcc-avr documentation but am still stuck. Any help welcome!

Here's a sketch demonstrating my problem...

void setup() {}

void loop() {

  byte thebyte = 128;  //0-127 works, >127 causes "impossible constraint"
  
  asm volatile (
  "ldi r16,%[thebyte]"    "\n\t"

    :: 
    
  [thebyte] "M" (thebyte)
    );

}

Looking at the avg-gcc source, the "M" constraint that you are using only allows unsigned values (0..255). There does not appear to be a constraint that would allow values in the signed range (-128..127).

That suggests that instruction takes a signed byte offset, so the value cannot be more than 127. Replace "byte" by "char" and 128 by -128 (unless you want +128 in which case perhaps a different instruction sequence is needed?)

Ok, I've sorted it.

Mistake number 1:

ldi loads an immediate value, e.g. a constant. No good for passing in values which change.

Mistake number 2:

Specifying "M" in the input parameter binding, again, it's for use with constants.

What I should have been doing is using the mov instruction, and passing in using the "r" option, so that the value goes into a register.

So, the fixed code:

void setup() {}

void loop() {

  byte thebyte = 128;  //This works as intended, right up to 255
  
  asm volatile (
  "mov r16,%0"    "\n\t"

    ::"r" (thebyte)
    );

}

Oh and thanks Mark for having a go, and not saying "you shouldn't be using assembler" :wink: