跳轉到內容

嵌入式系統/ARM 微處理器

來自華夏公益教科書

ARM 架構是一種廣泛使用的 32 位 RISC 處理器架構。事實上,ARM 系列約佔所有 32 位 CPU 的 75%,約佔所有嵌入式 32 位 CPU 的 90%。ARM 有限公司將幾個流行的微處理器核心授權給許多供應商(ARM 不出售物理微處理器)。最初,ARM 代表高階精簡指令集機器

ARM 提供的一些核心

  • ARM7TDMI
  • ARM9
  • ARM11

一些基於 ARM 的處理器的示例

  • 英特爾 X-Scale(PXA-255 和 PXA-270),用於 Palm PDA
  • 飛利浦 LPC2000 系列 (ARM7TDMI-S 核心),LPC3000 系列 (ARM9 核心)
  • Atmel AT91SAM7 (ARM7TDMI 核心)
  • 意法半導體 STR710 (ARM7TDMI 核心)
  • 飛思卡爾 MCIMX27 系列 (ARM9 核心)

最便宜的 ARM 處理器(LPC2000 系列)的價格已降至 5 美元以下,低於許多 16 位和 8 位微處理器的價格。

Thumb 呼叫約定

[編輯 | 編輯原始碼]

在 ARM Thumb 程式碼中,16 個暫存器 r0 - r15 通常在所有 ARM 程式碼中具有相同的角色

  • r0 - r3,稱為 a1 - a4:引數/臨時/結果暫存器。
  • r4 - r9,稱為 v1 - v6:變數
  • r10,稱為 sl:堆疊限制
  • r11,稱為 fp:幀指標(通常在 Thumb 程式碼中不使用)
  • r12,稱為 ip
  • r13,稱為 sp:堆疊指標
  • r14,稱為 lr:連結暫存器
  • r15,稱為 pc:程式計數器

ARM Thumb 的標準 C 呼叫約定是:[1]

子程式保留暫存器

[編輯 | 編輯原始碼]

當返回地址放置在 pc (r15) 中時,從子程式返回時,sp、fp、sl 和 v1-v6 暫存器必須包含與呼叫子程式時相同的

每個執行環境都對堆疊在記憶體中下降的範圍有限制——“最小 sp”。

為了讓中斷(可能在任何時候發生)有空間工作,在任何時刻,sp 和“最小 sp”之間的記憶體必須不包含對正在執行的程式

應用程式及其庫支援程式碼負責檢測和處理堆疊溢位的系統稱為“顯式堆疊限制”。在這樣的系統中,sl 暫存器必須始終

呼叫者保留暫存器

[編輯 | 編輯原始碼]

子程式可以隨意覆蓋 a1-a4、ip 和 lr。

返回值

[編輯 | 編輯原始碼]

如果子程式返回一個不超過一個字的簡單值,則該值必須在 a1 (r0) 中。

如果子程式返回一個簡單的浮點值,則該值編碼在 a1 中;或者 {a1, a2} 中;或者 {a1, a2, a3} 中,以

典型子程式

[編輯 | 編輯原始碼]

Thumb 函式最簡單的入口和退出序列是:[1]

an_example_Thumb_subroutine:
    PUSH {save-registers, lr} ; one-line entry sequence
    ; ... first part of function ...
    BL subroutine_name 	;Must be in a space of +/- 4 MB 
    ; ... rest of function goes here, perhaps including other function calls
    ; ...
    POP {save-registers, pc} ; one-line exit sequence

ARM 呼叫約定

[編輯 | 編輯原始碼]

ARM 的標準 C 呼叫約定由 ARM PLC 詳細說明。[2]

32 位 ARM 函式最簡單的入口和退出序列與 Thumb 函式非常相似:[3][4][5]

an_example_ARM32_subroutine:
    PUSH {r4-r11, lr} ; one-line function prologue
    ; ... first part of function ...
    BL subroutine_name 	;Must be in a space of +/- 4 MB 
    ; ... rest of function goes here, perhaps including other function calls
    ; ...
    POP {r4-r11, pc} ; one-line exit sequence (function epilogue)

使用相同指令的備用助記符,

an_example_ARM32_subroutine:
    ; Push the return address (in LR) and the work registers
    ; "store multiple registers, full descending"
    STMFD sp!,{r4-r11, lr} ; aka PUSH {r4-r11, lr}
    ; (A "sp" alone would leave the stack pointer unchanged.
    ; We must use "sp!" to update the stack pointer appropriately.)
    ; ... first part of function ...
    BL subroutine_name 	;Must be in a space of +/- 4 MB 
    ; ... rest of function goes here, perhaps including other function calls
    ; ...
    ; Pop the return address (into PC) and the work registers
    ; and return automatically.    
    ; "load multiple registers, full descending"
    LDMFD sp!,{r4-r11, pc} ; aka POP {r4-r11, pc}

BL(分支並連結)指令將返回地址儲存在連結暫存器 LR(r14)中,並將程式計數器 PC(r15)載入到子程式地址。典型

子程式保留暫存器

[編輯 | 編輯原始碼]

通常,r4-r11 用於儲存當前正在執行的例程的區域性變數。

暫存器 r4-r11 是“子程式保留暫存器”——當子程式將返回地址放置在 pc (r15) 中時,從子程式返回時,暫存器 r4-r11

典型的子程式(如上所示)會立即將這些暫存器的值壓入堆疊。這釋放了 r4-r11 以儲存當前正在執行的子程式的區域性

最佳化的 ARM 編譯器會儲存和恢復 r4-r11 和 r14(如果有)的精確子集,這些子集實際上被該子程式修改了,因為儲存和

臨時暫存器

[編輯 | 編輯原始碼]

子程式可以隨意覆蓋 r0-r3、r12 和連結暫存器 lr (r14)。

前四個暫存器 r0-r3 用於將引數值傳遞給子程式,並從函式返回結果值。

混合 ARM32 和 Thumb 呼叫

[編輯 | 編輯原始碼]

使用 BL 指令可以輕鬆進行正常的函式呼叫。一個人輸入

    BL destination_subroutine

彙編器和連結器會自動執行“正確的事情” - 插入適當的(32 位長)ARM32 BL 指令用於 ARM32 到 ARM32 或 ARM32 到 Thumb 的呼叫,或插入適當的(32 位長)[6] Thumb BL 指令用於 Thumb 到 Thumb 或 Thumb 到 ARM32 的指令。

(一些混合呼叫和一些長分支需要連結器插入程式碼,用臨時值覆蓋 scratch register r12。 連結器究竟是如何做到的可能會令人困惑,尤其是在混合使用 BX 和 BLX 指令時。[7][8]

進一步閱讀

[edit | edit source]
  1. a b ARM. ARM 軟體開發工具包. 1997. 第 9 章:ARM 過程呼叫標準。 第 10 章:Thumb 過程呼叫標準。
  2. "ARM 架構過程呼叫標準"
  3. RealView 編譯工具開發者指南 "在 C、C++ 和 ARM 組合語言之間呼叫"
  4. [1] 第 59 頁“堆疊和子程式”部分
  5. "為巢狀子程式堆疊暫存器"
  6. [infocenter.arm.com/help/topic/com.arm.doc.ddi0234b/i107462.html "帶有連結的 Thumb 分支 (BL)"]
  7. "Arm/Thumb:在 Thumb 程式碼中使用 BX,呼叫 Thumb 函式,或跳轉到另一個函式中的 Thumb 指令"
  8. "Arm / Thumb 互操作"
華夏公益教科書