筆者來聊聊ARM的函數的調用規則
1、ARM函數調用規則介紹
首先介紹幾個術語,
- AAPCS:Procedure Call Standard for the ARM Architecture
- APCS:ARM Procedure Call Standard
- TPCS:Thumb Procedure Call Standard
- ATPCS:ARM-Thumb Procedure Call Standard
- ABI:Application Binary Interface
- EABI:Embedded Application Binary Interface
前三個基本就是ARM 架構的程式調用标準(包括ARM指令以及thumb指令),最後兩個是程式二進制接口,描述是彙編下面寄存器名使用、函數調用、壓棧、參數傳遞以及程式傳回等一系列接口标準。
比如x86與arm架構的ABI 就不相容,寄存器都不一樣,肯定就是無法互相使用,包括最近比較火熱的RISC-V架構。
2、ARM32/64 函數調用規則
ARM架構下面分為32位以及64位的程式,其标準有些不同以及擴充,可分開來講。
2.1、ARM
-
機器寄存器
對于ARM以及thumb指令集來說,總有16個寄存器使用,不管大小寫,在彙編語言裡面都是可以識别的,一般來說大寫的有特殊用途,詳情見下文。
- R0-R3 作為函數參數傳遞以及傳回值使用,也可以在程式中儲存立即數。
- R12 (IP)連結器使用的暫存器
- R9 平台寄存器,ARM不推薦使用,避免平台依賴
- R4-R8,R10,R11 暫存器
- R11 作為棧指針,指向程式調用中開辟空間的棧底,可用來棧回溯,具體可以參考ARMARM學習(1) 寄存器的了解 ===》FP、SP、LR寄存器。
- R13 SP 棧指針
- R14 LR 連結寄存器
- R15 PC 程式計數器
- CPSR 狀态寄存器 詳情介紹見ARM學習(2) 寄存器的了解 ===》通用寄存器及狀态寄存器。
- cp15 協處理 監控通用寄存器的使用
-
程式處理、記憶體以及棧
一個程式的記憶體通常會劃分為幾部分:Code、read-only static data、writeable static data、heap and stack,Code段裡面會包括read-only static data,DATA段會包括初始化好的全局變量,BSS包括堆棧以及未初始化和初始化為0的全局變量
- stack 臨時存儲變量以及傳遞額外的參數(程式調用時寄存器數量不足),
- 棧有範圍限制,Limit < SP < Base
- 其次必須4 byte對齊,
- 程式必須通路棧的部分範圍内區域(SP ,base-1),不能通路之外的區域,
- 子程式調用
- BL指令會跳到目标程式,并且修改LR為目前PC的按順序下一條指令位址,指的是沒跳轉之前的PC的下一條。
- 需要注意修改LR最低位表示目前為什麼狀态,,0:是arm狀态,無需修改(因為位址都是word 2Byte對齊的),1:是thumb狀态,需要修改, 可以看到R14以及PC的值都是奇數,代表是thumb指令。
R15(PC):0x0801247E 位于 DMA_GetFlagStatus,
R14:0x08014ECB 位于 UART1_SentMsgL,儲存了其傳回的位址。
- 傳回值
- R0:傳回值是D-Word(32 bit),或者是單精度浮點型float,
- R0-R1:傳回值是Q-Word(64 bit),或者雙精度浮點型double
- R0-R3:傳回值是128bit的向量 調用GetSysTime之後,r0則擷取到值,然後r1計算好之後,則cmp進行比較r0,r1.
- 參數傳遞
- R0-R3 和棧進行傳遞
- 參數少的函數,隻用寄存器就可以了,減少通路記憶體帶來的負載
-
優先寄存器,然後棧,寄存器從小到大,棧位址從小到大。
1、函數聲明:void OLED_DrawBMP_test(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[],unsigned char state1,unsigned char state2);
2、共用7個參數:x0,y0,x1,y1,BMP[],state1,state2
3、前四個參數都分别存儲在r0-r3,
4、後面三個參數存儲在棧中,strd r7,r6,[r13] 以及str r6,[r13,#0x8] ,前面指令存儲r7 r6 兩個參數,後面位址偏移8之後,又存儲一個參數,總計三個參數,存儲順序依次都是參數從左向右去存儲。
5、不符合__cdecl、__stdcall、__fastcall這三種調用标準。
- 内部聯合工作(ARM與Thumb指令)
- 子程式調用和程式傳回支援兩張狀态切換。bx或者blx都可以切換狀态。
2.2、ARM64
參考文檔
1、ARM Procedure Call Standard
2、Procedure Call Standard for the ARM 64-bit Architecture (AArch64)