链接文件格式.lds
在最终生成可执行文件的时候,会确定各个段的位置
SECTIONS {
.text 0 : {*(.text)}//所有文件的.text段都放在地址0开始的位置
.rodata :{*(.rodata)}//所有文件的.rodata段都放在地址.text地址之后
.data 0x30000000 : AT(0x800)//数据段 运行的地址是0x30000000 : 加载的地址是0x800
{
data_load_addr = LOADADDR(.data); //让变量data_load_addr 等于数据的起始地址
. = ALGN(4) //让data段开始的位置在4字节对齐的地址
data_start = . ; //变量data_start 等于当前地址
*(.data)//存放所有数据段,当前地址会根据data的大小而进行增加
data_end = . ; //变量data_end 等于当前地址, 这个当前的地址是data_start+*(.data)后的位置
}
. = ALIGN(4); //让bss段开始的位置在4字节对齐的地址
bss_start = .; //变量bss_start 等于当前地址
.bss :{*(.bss) *(.COMMON)} //存放所有bss和commen段,bss没有写运行地址和加载地址,所以默认是data段之后的位置。 当前地址会根据bss和comment的大小而增加
bss_end = .;//变量bss_start 等于当前地址, 这个当前地址是bss_start+*(.bss) +*(.COMMON)后的位置
}
语法格式:
主要分成下面四个部分,中间用:间隔
段名 运行地址或者重定位后的地址 : 加载地址 {内容}
- 加载地址如果没有,就默认和前面的运行地址一致
- 运行地址或者重定位后的地址没有,就表明这个段和紧跟上面段后面
- 内容由{ }包起来,里面可以有多条语句
关于存放4字节对齐:ALIGN(4)
以下面代码为例
char g_Char = 'A';
char g_Char3 = 'a';
int g_A = 0;
int g_B;
int main(void)
{
...
}
上面的代码如果不进行对齐存放的话,加载到内存会是这样的情况,如果要对整型数据g_A进行操作,那么其实地址是0x30000002, 对于32位的CPU,当它对整型数据操作时,会默认从4字节对齐的位置操作,也就是,你要操作0x30000002,那么,cpu会自动把地址更换成0x3000000 。这样的话你就会改动g_char 和 g_char3这两个数据和g_A的前2个字节。
如果在链接的时候使用 ALIGN(4)进行字节对齐存放,会变成下面的样子。如果要对整型数据g_A进行操作,那么其实地址是0x30000004,对于32位cpu来说,是符合4字节对齐的地址。那么就能正确的操作g_A的4个字节数