С помощью ассемблера GNU / binutils. Я очень ржавый на моем avr, но ...
so.s
.globl _start
_start:
nop
nop
rcall fun
nop
nop
here:
rjmp here
fun.s
.globl fun
fun:
nop
nop
ret
build
avr-as so.s -o so.o
avr-as fun.s -o fun.o
avr-ld -Ttext=0 so.o fun.o -o so.elf
avr-objdump -d so.elf
so.elf: file format elf32-avr
Disassembly of section .text:
00000000 <__ctors_end>:
0: 00 00 nop
2: 00 00 nop
4: 03 d0 rcall .+6 ; 0xc <fun>
6: 00 00 nop
...
0000000a <here>:
a: ff cf rjmp .-2 ; 0xa <here>
0000000c <fun>:
c: 00 00 nop
e: 00 00 nop
10: 08 95 ret
язык ассемблера указывается c ассемблеру, а не целевому объекту, поэтому вам нужно использовать язык ассемблера, который вы используете, это gnu ассемблер для avr. Точно так же то, как вы их связываете, очень сильно зависит от инструмента c. gnu ld имеет множество функций, AVR - это PITA, для которого нужно создать (с нуля), поэтому вы можете использовать уже созданный набор инструментов и скрипт компоновщика. (на linux я просто получил набор инструментов).
Как бы ужасно это ни было:
avr-gcc -nostdlib so.s fun.s -o so.elf
avr-objdump -d so.elf
so.elf: file format elf32-avr
Disassembly of section .text:
00000000 <__ctors_end>:
0: 00 00 nop
2: 00 00 nop
4: 03 d0 rcall .+6 ; 0xc <fun>
6: 00 00 nop
...
0000000a <here>:
a: ff cf rjmp .-2 ; 0xa <here>
0000000c <fun>:
c: 00 00 nop
e: 00 00 nop
10: 08 95 ret
работает (пока).