I figured out how to assemble without error messages.
The error messages you see are caused by the fact that avr-as
does not invoke the C-preprocessor and therefore the #include
lines are read as regular comments.
Create a file ledON.S
and notice the CAPITAL S
in the filename. The capital S
indicates that the C-preprocessor must be invoked first. Create the file with the following content:
#include <avr/io.h>
init: sbi _SFR_IO_ADDR(DDRB),0x05 ; Configure port B pin 5 as output
ret
.global main
main:
call init
loop:
sbi _SFR_IO_ADDR(PORTB),0x05 ; Toggle output pin HIGH
cbi _SFR_IO_ADDR(PORTB),0x05 ; Toggle output pin LOW
rjmp loop
The main
part is required in the source code, this is where usually the main program is located. If you remove it, no real code is executed ever and thus the compiler will complain about that. Code in a routine called init
should be explicitly called from main
. Although the pin toggles, in practice this will be too fast to see with the bare eye. If you check with an oscilloscope you'll see a square wave (I estimate at 25% duty cycle).
Then assemble the source code with:
avr-gcc -mmcu=atmega168a ledON.S -o ledON.o
Again avr-gcc
is required to invoke the C-preprocessor.
To check the result of the assembled program run the following command:
avr-objdump -C -d ./ledON.o
And the resulting disassembly listing looks like this:
./ledON.o: file format elf32-avr
Disassembly of section .text:
00000000 <__vectors>:
0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>
4: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
8: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
10: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
14: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
18: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
1c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
20: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
24: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
28: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
2c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
30: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
34: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
38: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
3c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
40: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
44: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
48: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
4c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
50: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
54: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
58: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
5c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
60: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
64: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
00000068 <__ctors_end>:
68: 11 24 eor r1, r1
6a: 1f be out 0x3f, r1 ; 63
6c: cf ef ldi r28, 0xFF ; 255
6e: d4 e0 ldi r29, 0x04 ; 4
70: de bf out 0x3e, r29 ; 62
72: cd bf out 0x3d, r28 ; 61
74: 0e 94 42 00 call 0x84 ; 0x84 <main>
78: 0c 94 47 00 jmp 0x8e ; 0x8e <_exit>
0000007c <__bad_interrupt>:
7c: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>
00000080 <init>:
80: 25 9a sbi 0x04, 5 ; 4
82: 08 95 ret
00000084 <main>:
84: 0e 94 40 00 call 0x80 ; 0x80 <init>
00000088 <loop>:
88: 2d 9a sbi 0x05, 5 ; 5
8a: 2d 98 cbi 0x05, 5 ; 5
8c: fd cf rjmp .-6 ; 0x88 <loop>
0000008e <_exit>:
8e: f8 94 cli
00000090 <__stop_program>:
90: ff cf rjmp .-2 ; 0x90 <__stop_program>
INTERMEZZO
You'll notice the assembler will automatically initialize the stack pointer
and status register in __ctors_end
.
Also it will automatically add a rjmp
at the end of the code.
Default behaviour of a program assembled by gcc-avr when it ends is:
- turn off interrupts (
_exit
, cli
)
- infinite empty loop that does nothing (
__stop_program
, rjmp .-2
)
avr-as
are you using, mine doesn't support the-c
flag, what does it do? \$\endgroup\$-c
flag im getting the same error :s \$\endgroup\$