Ever wonder what all of the code inserted at the beginning of your program that appears in a disassembly listing is about? Well it’s a bunch of required housekeeping routines that are linked into your program at compile time that come from several locations. Some of the files are Arduino specific while others are AVR GCC and libc code. Here is a breakdown of the basic “Blink” program running on a generic ATMega328.

First we see the interrupt vector table (IVT), which is a table of interrupt vectors that associates an interrupt handler with an interrupt request. More information can be found here and here.

Note the first vector, or reset vector is set to point to the code that begins at the label “__ctors_end”. With the exception of vector #16, the remaining vectors all point to the “bad interrupt code”. See this post for more information about bad interrupt handling. Vector #16 is the Timer0 overflow vector and is used by the Arduino millis timer. See here for more information on how millis works.

Next comes any program memory. For example, Arduino’s digitalWrite/Read functions use program memory for pin-mapping. Information on PROGMEM can be found here and here.

Next, the r1 register is zeroed (it’s assumed to always be zero throughout the program), and the SREG register is zeroed. Then our stack is initialized. The stack is used primarily to keep track of program execution and data passing to/from functions.

Next is data initialization code. First, the code copies global/static initialized variables into SRAM. Then, if any uninitialized variables exist, a copy BSS section is appended to your code. Finally, if there are any C++ constructor/destructors, a bit of additional code is inserted (none here). In the blink disassembly, 11 bytes of memory are copied: timer0_millis (4 bytes), timer0_overflow_count (4 bytes), timer0_fract (1 byte), and led (2 bytes).