首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Cortex-M3 動態載入 (一):位置無關代碼 (PIC) 的指令級實現機制

     編輯:關於C語言

背景

嵌入式系統中,動態載入模組要求代碼可在任意記憶體位址執行,即位置無關代碼 (Position Independent Code, PIC)。ARM 編譯器需指定 --apcs=/ropi/rwpi 選項啟用 ROPI (Read-Only Position Independence) 與 RWPI (Read-Write Position Independence)。

實驗環境

// main.c
void fun_for_sub(void) { int j; for (j=10; j>=0; j--); }
int main(void) { SystemInit(); fun_for_sub(); }
armcc -c --cpu Cortex-M3 -O0 --apcs=interwork --apcs=/ropi/rwpi -o main.o main.c
fromelf.exe -s -c main.o  # 反組譯查看

關鍵發現:BL 指令的 PC 相對寻址

反組譯輸出關鍵行:

0x00000006: F7FF FFFE  BL fun_for_sub  ; 0x2 Section

機器碼 F7FF FFFE 為 Thumb-2 BL (Branch with Link) 指令,編碼格式:

S | imm10 | J1 | J2 | imm11
15 14     4 3  2  1  0

指令解碼詳解

F7FF = 1111 0111 1111 1111
FFFE = 1111 1111 1111 1110

S=1, J1=1, J2=1, imm10=0x3FF, imm11=0x7FE

I1 = NOT(J1 XOR S) = NOT(1 XOR 1) = 1
I2 = NOT(J2 XOR S) = NOT(1 XOR 1) = 1

imm32 = SignExtend(S:I1:I2:imm10:imm11:'0', 32)
      = SignExtend(1:1:1:11_1111_1111:111_1111_1110:0, 32)
      = 0xFFFFFFFC  (= -4 有號數)

PC = 0x00000006 (BL 指令地址 + 4, Thumb 模式 PC 對齊)
目標地址 = PC + imm32 = 0x6 + (-4) = 0x2  → 正是 fun_for_sub 入口

核心結論

  1. BL 使用 PC 相對偏移:而非絕對位址,編譯時計算相對偏移,執行時 PC + offset 定址
  2. 代碼段內部跳轉天然 PIC:只要代碼段整體平移,相對位移不變
  3. 資料存取需額外機制:全域變數、常數池存取需透過 PC + offset 計算基址 (GOT 表或直接 PC 相對載入)

x86 對比

x86 同樣使用 CALL rel32 (E8 cd) 相對呼叫指令實現 PIC。《程式設計師的自我修養》詳述鏈接器如何處理重定位項生成位置無關可執行檔 (PIE)。

工程啟示

  • 嵌入式 Bootloader 應用程式跳轉:BL/B 相對跳轉無需修正
  • 動態載入器:載入代碼段後,僅需修正資料段參考 (GOT/重定位表)
  • --apcs=/ropi 強制編譯器生成 PC 相對存取常數池、全域變數

結語

Cortex-M3 Thumb-2 指令集的 BL 採用 23 位元有號 PC 相對偏移 (±16MB 範圍),配合編譯器生成的相對偏移,使代碼段內部控制流轉移天然具備位置無關特性。這是動態載入、模組化韌體、Bootloader 設計的指令級基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved