链接脚本
2025/8/22大约 1 分钟
链接脚本
// start.c
void Reset_Handler(void) {
// 启动代码...
main();
}
// main.c
#include <stdio.h>
const char msg[] = "Hello"; // 只读数据(.rodata)
int a = 123; // 已初始化全局变量(.data)
int b; // 未初始化全局变量(.bss)
int main(void) {
b = a + 1;
printf("%s %d\n", msg, b);
while (1);
}0x87800000 → .text 段(代码段)
start.o 的机器码(Reset_Handler)
main.o 的机器码(main 函数)
其他 .o 文件的 .text
0x87801234 → .rodata 段(只读数据)
"Hello" 常量字符串
0x87801240 → .data 段(已初始化全局变量)
a = 123
__bss_start = 0x87801250
0x87801250 → .bss 段(未初始化全局变量)
b(启动时会被清零)
__bss_end = 0x87801254假设 SDRAM 从 0x87800000 开始存程序,链接脚本是这样安排的
程序启动流程
- CPU 上电 → 从
0x87800000(.text 段开头)取指令执行。 - 运行 start.o 里的启动代码:
- 复制
.data段的初始值(从 Flash 拷到 RAM 0x87801240) - 把
.bss段(0x87801250 ~ 0x87801254)清零 - 跳到
main()
- 复制
main()运行时:- 访问
"Hello"时,取的是.rodata段 0x87801234 - 访问
a取的是.data段 0x87801240 - 访问
b取的是.bss段 0x87801250
- 访问
SDRAM (0x87800000 起)
┌───────────────────────────────┐
│ .text │ 0x87800000
│ - start.o 机器码 │
│ - main.o 机器码 │
│ - 其他函数 │
├───────────────────────────────┤
│ .rodata (对齐到4字节) │ 0x87801234
│ - "Hello" │
├───────────────────────────────┤
│ .data (对齐到4字节) │ 0x87801240
│ - a = 123 │
├───────────────────────────────┤
│ .bss (对齐到4字节) │ 0x87801250 = __bss_start
│ - b(初值0) │
│ │ 0x87801254 = __bss_end
└───────────────────────────────┘
