The following blink program runs fine on my Attiny85 SparkFun Tiny AVR programmer board. It produces 5 short blinks and then stops.

It also works fine when I change r16 to any one of the registers r17, r21 or r29. But trying with any other register gives either no blink at all (r19, r20, r23, r25, r26, r27, r28, r31) or indefinite blinks (r18, r22, r24, r30).

Can anyone explain?

int ledPin = 0;

void setup() {

  pinMode(ledPin, OUTPUT);

  asm("ldi r16, 5");
  digitalWrite(ledPin, HIGH);
  digitalWrite(ledPin, LOW);
  asm("dec r16");
  asm("brge blink");

void loop() {
  • Why are you trying to mix assembly in there like that without first knowing what registers are already being used by the program for other purposes? Either use C or use assembly. Don't mix them like that. – Majenko Mar 19 '20 at 22:33
  • I usually do not mix like this, but inserted the blink part for a debugging reason. Why I use inline assembly is to speed up an inner loop. – RobertFo Mar 20 '20 at 21:38

Solved it myself! The high-level command "delay(500)" destroys the register contents. Saving the register (using push/pop) while doing delay() solves this issue. (Btw, is should be "brpl" and not "brge".)


As you discovered, calling a function may clobber some registers. To be precise, the avr-gcc documentation says:

Call-Used Registers

The call-used or call-clobbered general purpose registers (GPRs) are registers that might be destroyed (clobbered) by a function call.

R18–R27, R30, R31 These GPRs are call clobbered. An ordinary function may use them without restoring the contents. Interrupt service routines (ISRs) must save and restore each register they use.

Call-Saved Registers

R2–R17, R28, R29 The remaining GPRs are call-saved, i.e. a function that uses such a registers must restore its original content. This applies even if the register is used to pass a function argument.

Now, an interesting detail here is that according to the documentation, one would expect R28 to work. Maybe that's not clobbered by the called procedure, but by your local procedure (mixing assembly and C in nontrivial amounts is a difficult task for precisely this reason).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.