Arduino programming in assembly?
I realize I can program the Arduino in C, but with my current project (tiny Arduino core) I would prefer to use Assembly for some sections to learn the assembly and possibly improve the efficiency of the SLIGHTEST bit.
Is there something I can use like __ASM __ ()? I was actually able to find people on the internet trying to convince people who asked similar questions to learn C rather than actually answering the question.
Thank!
source to share
one that I wrote and published many years ago.
.device ATmega168
.equ DDRB = 0x04
.equ PORTB = 0x05
.org 0x0000
rjmp RESET
RESET:
ldi R16,0x20
out DDRB,R16
ldi R18,0x00
ldi R17,0x00
ldi R20,0x20
Loop:
ldi R19,0xE8
aloop:
inc R17
cpi R17,0x00
brne aloop
inc R18
cpi R18,0x00
brne aloop
inc R19
cpi R19,0x00
brne aloop
eor R16,R20
out PORTB, R16
rjmp Loop
I used avra and probably wrote my own arduino bootloader
blinker01.s.hex : blinker01.s
avra -fI blinker01.s
clean :
rm -f blinker01.s.*
you could use avr_dude of course.
With gnu, something slightly different:
.globl _start
_start:
rjmp RESET
RESET:
ldi R18,0x00
ldi R17,0x00
ldi R20,0x20
Loop:
ldi R19,0xE8
aloop:
inc R17
cpi R17,0x00
brne aloop
inc R18
cpi R18,0x00
brne aloop
inc R19
cpi R19,0x00
brne aloop
rjmp Loop
you do not need header files to define ports, you can declare them yourself.
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
}
avr-as so.s -o so.o
avr-ld -T so.ld so.o -o so.elf
avr-objdump -D so.elf > so.list
avr-objcopy so.elf -O ihex so.hex
Using apt-got avr-gcc (and binutils), maybe the same tools used with arduino sandbox and should be accessed directly, but I'm not using sandbox so I don't know.
EDIT
the other approach is limited but more likely to succeed with the toolchain since you start with a working C application and environment, then add an object, also help with the basics of building, see what the compiler does, then read on it:
unsigned short fun ( unsigned short x, unsigned short y )
{
return(x+y+5);
}
avr-gcc -c -O2 so.c -o so.o
avr-objdump -D so.o
00000000 <fun>:
0: 6b 5f subi r22, 0xFB ; 251
2: 7f 4f sbci r23, 0xFF ; 255
4: 86 0f add r24, r22
6: 97 1f adc r25, r23
8: 08 95 ret
So
create so.s
.globl fun
fun:
subi r22, 0xFB ; 251
sbci r23, 0xFF ; 255
add r24, r22
adc r25, r23
ret
avr-as so.s -o so.o
avr-objdump -D so.o
00000000 <fun>:
0: 6b 5f subi r22, 0xFB ; 251
2: 7f 4f sbci r23, 0xFF ; 255
4: 86 0f add r24, r22
6: 97 1f adc r25, r23
8: 08 95 ret
and then instead of linking in the generated object C a reference to the object created by the assembly, you should learn the calling convention, which you can experiment with.
unsigned char fun ( unsigned char x, unsigned char y )
{
return(x+(y<<1));
}
00000000 <fun>:
0: 66 0f add r22, r22
2: 86 0f add r24, r22
4: 08 95 ret
in this case the second parameter in r22 is first in r24, the return value in r24. so 22/23 is probably for the first parameter for large items like the short one, and 24/25 for the second. it will be documented somewhere as well, the compiler matches it, there will be exceptions, so create a correct example to see what the compiler does and not just assume that everything from one example is critical, even if you read the docs, this is probably vaguely, or uses terminology that may not make sense until you experiment.
source to share