This looks like a bug in the toolchain: an off-by-one error in all relative jumps. For example, the main loop:
loop {
write_reg(portB, 1 << LED_BUILTIN, 1 << LED_BUILTIN);
delay(500_0000);
write_reg(portB, 0, 1 << LED_BUILTIN);
delay(500_0000);
}
got translated to this by RUSTFLAGS="--emit asm"
:
.LBB1_1:
sbi 5, 5
call _ZN13arduino_blink5delay17h9627a982856e7dadE
cbi 5, 5
call _ZN13arduino_blink5delay17h9627a982856e7dadE
rjmp .LBB1_1
which looks correct to me. However, on the disassembly of the final program, it looks like this:
b0: 2d 9a sbi 0x05, 5 ; PORTB |= (1<<5);
b2: 0e 94 40 00 call 0x80 ; loop: delay();
b6: 2d 98 cbi 0x05, 5 ; PORTB &= ~(1<<5);
b8: 0e 94 40 00 call 0x80 ; delay();
bc: fa cf rjmp .-12 ; goto loop; // 0xb2
The instruction that turns the LED on is now out of the loop. There are
other similar off-by-one errors within the delay function, on the
instructions brcs
, breq
and rjmp
.
I have no idea how to solve this, other than looking at the bug tracker of the AVR Rust toolchain.
Edit: The Arduino IDE does not come with a Rust compiler. You are
thus using a separate, presumably experimental, compiler. My guess is
that, unless explicitly asked to --emit asm
, this Rust compiler
compiles directly to machine code. It is pretty common nowadays to skip
the assembly language and compile from a high-level language directly to
machine code.
The first assembly snippet was obtained with --emit asm
. It is not
really a "disassembly", but the result of a direct Rust → asm
translation. The second snipped, generated by avr-objdump
is a proper
disassembly: the result of a Rust → machine code → asm
translation.
My guess is that the bug lies in the Rust → machine code
translation, which is why it does not affect the --emit asm
output.
Relative jumps on AVR are a bit unintuitive: they are relative to the
program counter, which is a CPU register holding the address of the
next instruction in the program. If you incorrectly assume these
jumps are relative to the current instruction, you get precisely the
faulty code of the second snippet.
- 45.1k
- 4
- 42
- 81