AVR-GCC中汇编器生成的目标文件至少包含4个段,分别为:
.text Section
data Section
.bss Section
.eeprom Section
他们包括了程序存储器(FLash),数据存储器ram,eeprom存储器的使用量,关系如下:
程序存储器(FLASH)使用 = .text+.data
数据存储器(RAM)使用量 =.data+.bss[+.noinit]+stack[+heap]
EEPROM存储器使用量 = .eeprom 。
The .text Section
.text Section包含程序实际执行代码。另外,还包含.initN Section和.finiN Section两种。
The .initN Sections
The .initN sections are executed in order from 0 to 9.
.init0:
Weakly bound to __init(). If user defines __init(), it will be jumped into immediately after a reset.
.init1:
Unused. User definable.
.init2:
In C programs, weakly bound to initialize the stack, and to clear __zero_reg__ (r1).
.init3:
Unused. User definable.
.init4:
For devices with > 64 KB of ROM, .init4 defines the code which takes care of copying the contents of .data from the flash to SRAM. For all other devices, this code as well as the code to zero out the .bss section is loaded from libgcc.a.
.init5:
Unused. User definable.
.init6:
Unused for C programs, but used for constructors in C++ programs.
.init7:
Unused. User definable.
.init8:
Unused. User definable.
.init9:
Jumps into main().
The .finiN Sections
这些部分是用来定义退出代码执行后返回从main()或exit()调用退出。
The .finiN sections按降序执行从9到0。
.finit9:
Unused. User definable. This is effectively where _exit() starts.
.fini8:
Unused. User definable.
.fini7:
Unused. User definable.
.fini6:
Unused for C programs, but used for destructors in C++ programs.
.fini5:
Unused. User definable.
.fini4:
Unused. User definable.
.fini3:
Unused. User definable.
.fini2:
Unused. User definable.
.fini1:
Unused. User definable.
.fini0:
Goes into an infinite loop after program termination and completion of any _exit() code (execution of code in the .fini9 -> .fini1 sections).
The .data Section
包含程序中被初始化的ram区全局或静态变量。而对于FLASH存储器。此段包含在程序中定义变量的初始化数据。类似如下的代码将生成.data段数据。
char err_str[] = "Your program has died a horrible death!";
struct point pt = { 1, 1 };
It is possible to tell the linker the SRAM address of the beginning of the .data section. This is accomplished by adding -Wl,-Tdata,addr to the avr-gcc command used to the link your program. Not that addr must be offset by adding 0x800000 the to real SRAM address so that the linker knows that the address is in the SRAM memory space. Thus, if you want the .data section to start at 0x1100, pass 0x801100 at the address to the linker.
The .bss Section
没有被初始化的ram区全局或静态变量被分配到此段,在应用程序被执行前的startup过程中这些变量被清零。
另外,.bss段有一个子段.noinit,若变量被指定到.noinit段中则在startup 过程中不会被清零。将变量指定到.noinit段的方法如下:
int foo __attribute__ ((section (".noinit")));
在启动时将不会被初始化为零。
由于指定到了.noinit段中,所以不能赋初值,如同以下代码在编译时产生错误:
int bar __attribute__ ((section (".noinit"))) = 0xaa;
利用.noinit段变量可以在复位时判断是否是上电复位。
The .eeprom Section 这就是eepm 变量存储。
在汇编中使用:
#include
.section .init1,"ax",@progbits
ldi r0, 0xff
out _SFR_IO_ADDR(PORTB), r0
out _SFR_IO_ADDR(DDRB), r0
在C中使用
#include
void my_init_portb (void) __attribute__ ((naked)) \
__attribute__ ((section (".init3")));
void
my_init_portb (void)
{
PORTB = 0xff;
DDRB = 0xff;
}
参考:http://www.atmel.com/webdoc/AVRLibcReferenceManual/mem_sections.html