I'm trying to write some assembly language for Arduino Duemilanove (AVR ATmega328P). Learning assembly language jointly in parallel with compiling and disassembling C code, I have got this:
(Compiled with AVR_GCC)
int main() {
volatile int a = 0;
while (1) {
++a;
}
return 0;
}
Which turns into
00000000 <__vectors>:
0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>
4: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
...
64: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__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: d8 e0 ldi r29, 0x08 ; 8
70: de bf out 0x3e, r29 ; 62
72: cd bf out 0x3d, r28 ; 61
00000074 <__do_copy_data>:
74: 11 e0 ldi r17, 0x01 ; 1
76: a0 e0 ldi r26, 0x00 ; 0
78: b1 e0 ldi r27, 0x01 ; 1
7a: e4 ec ldi r30, 0xC4 ; 196
7c: f0 e0 ldi r31, 0x00 ; 0
7e: 02 c0 rjmp .+4 ; 0x84 <__do_copy_data+0x10>
80: 05 90 lpm r0, Z+
82: 0d 92 st X+, r0
84: a0 30 cpi r26, 0x00 ; 0
86: b1 07 cpc r27, r17
88: d9 f7 brne .-10 ; 0x80 <__do_copy_data+0xc>
0000008a <__do_clear_bss>:
8a: 11 e0 ldi r17, 0x01 ; 1
8c: a0 e0 ldi r26, 0x00 ; 0
8e: b1 e0 ldi r27, 0x01 ; 1
90: 01 c0 rjmp .+2 ; 0x94 <.do_clear_bss_start>
00000092 <.do_clear_bss_loop>:
92: 1d 92 st X+, r1
00000094 <.do_clear_bss_start>:
94: a0 30 cpi r26, 0x00 ; 0
96: b1 07 cpc r27, r17
98: e1 f7 brne .-8 ; 0x92 <.do_clear_bss_loop>
9a: 0e 94 53 00 call 0xa6 ; 0xa6 <main>
9e: 0c 94 60 00 jmp 0xc0 ; 0xc0 <_exit>
000000a2 <__bad_interrupt>:
a2: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>
000000a6 <main>:
a6: cf 93 push r28
a8: df 93 push r29
aa: 00 d0 rcall .+0 ; 0xac <main+0x6>
ac: cd b7 in r28, 0x3d ; 61
ae: de b7 in r29, 0x3e ; 62
b0: 1a 82 std Y+2, r1 ; 0x02
b2: 19 82 std Y+1, r1 ; 0x01
b4: 89 81 ldd r24, Y+1 ; 0x01
b6: 9a 81 ldd r25, Y+2 ; 0x02
b8: 01 96 adiw r24, 0x01 ; 1
ba: 9a 83 std Y+2, r25 ; 0x02
bc: 89 83 std Y+1, r24 ; 0x01
be: fa cf rjmp .-12 ; 0xb4 <main+0xe>
000000c0 <_exit>:
c0: f8 94 cli
000000c2 <__stop_program>:
c2: ff cf rjmp .-2 ; 0xc2 <__stop_program>
I tried to understand a few things:
main
. Any general explanations?ldi r17, 1
? We did that before (just a stupid remark). Or can something else alter r17?The dot/period is used as a shortcut to indicate this instruction's address or location or something relative to that. .+8 means from here plus 8. You have to account for the nuances of the instruction set and/or assembler relative to the instruction set. As the additional information from the assembler indicates, the .-8 is going to do_clear_bss_loop
which is eight bytes back including the two bytes for the instruction itself. The original code probably just had the label in there, brne do_clear_bss_loop
.
It is likely copying the data segment; .text
is basically read-only. It is your code and it wants to live in flash on this platform. .data
, though, is read/write and usually initialized to non-zero values. So with the power off, your initial values need to be preserved somewhere, in flash for example, but before you start your real program the bootstrap will need to copy the initial .data segment values from flash to their actual home in RAM. Then as the program runs, it can read and/or modify those values as desired.
For example:
int x = 5;
main ()
{
x = x + 1;
}
That value 5 has to be in flash in order to start from power up only using flash to hold non-volatile information. But before you can read/write the memory location for x you need it in RAM, so some startup code copies all of the .data
sgement stuff from flash to RAM.
Sorry for that long explanation for something that is only a guess looking at your question.
.bss
are variables in your program that are initialized to zero. With the .data
segment, if we had 100 items we would need 100 things in flash. But with .bss
if we have 100 items we only need to tell someone that there are 100 items. We don't need 100 zeros in flash, just compile/assemble it into the code.
So
int x = 5;
int y;
int main ()
{
while(1)
{
y = y + x + 1;
}
}
x
is in .data
and the 5 needs to be in non-volatile storage. The y is in .bss
and only needs to be zeroed before main is called to comply with the C standard.
Granted, you may not be using global variables yourself, but there may be other data that is in some way using the .data
and/or .bss
segments and as a result the bootstrap code prepares the .data
and .bss
segments before calling main()
so that your C programming experience is as expected.