ARM 裸機啟動代碼(`start.S`)執行順序:
clr_bss:
ldr r0, _bss_start @ __bss_start 地址
ldr r1, _bss_end @ __bss_end 地址
mov r2, #0
forclrbss:
cmp r0, r1
bge endclrbss
strb r2, [r0], #1 @ 逐字節清零,後增寻址
b forclrbss
endclrbss:
...
OUTPUT_FORMAT("elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS {
. = 0x40008000; @ 載入地址
.text : {
start.o(.text); @ 啟動代碼優先
*(.text); @ 其餘代碼段
}
. = ALIGN(4);
.data : { *(.data); } @ 已初始化全局/靜態變量
. = ALIGN(4);
__bss_start = .; @ BSS 起始標記(關鍵符號)
.bss : { *(.bss); } @ 未初始化全局/靜態變量
__bss_end = .; @ BSS 結束標記
}
| 符號 | 定義位置 | 用途 |
|---|---|---|
| `__bss_start` | 鏈接腳本 | BSS 段起始地址,`start.S` 通過 `_bss_start` 訪問 |
| `__bss_end` | 鏈接腳本 | BSS 段結束地址,`start.S` 通過 `_bss_end` 訪問 |
| `_start` | start.S | 程序入口,鏈接腳本 `ENTRY(_start)` 指定 |
| `entry` | C 代碼 | 用戶主函數(如 `main`),啟動代碼 `bl entry` 調用 |
C 標準規定:靜態存儲期變量未顯式初始化時,默認初始化為 0。鏈接器不為 BSS 分配文件空間(僅記錄大小),加載器也不保證內存為零,因此啟動代碼必須在進入 `main` 前將 `__bss_start` 到 `__bss_end` 區間清零。