1. 程式人生 > >ARM彙編基礎知識學習1(ARMV7 32位)

ARM彙編基礎知識學習1(ARMV7 32位)

ARM基礎知識部分(ARMV7 32位)
首先你介紹一下暫存器: R0-R3:用於函式引數及返回值的傳遞 R4-R6, R8, R10-R11:沒有特殊規定,就是普通的通用暫存器 R7:棧幀指標(Frame Pointer).指向前一個儲存的棧幀(stack frame)和連結暫存器(link register, lr)在棧上的地址。 R9:作業系統保留 R13:又叫SP(stack pointer),是棧頂指標 R14:又叫LR(link register),存放函式的返回地址。 R15:又叫PC(program counter),指向當前指令地址。 CPSR:當前程式狀態暫存器(Current Program State Register),在使用者狀態下存放像condition標誌中斷禁用等標誌的。      在其它系統狀態中斷狀等狀態下與CPSR對應還有一個SPSR,在這裡不詳述了。 另外還有VFP(向量浮點運算)相關的暫存器,在此我們略過,感興趣的可以從後面的參考連結去檢視。
基本的指令:
add 加指令 sub 減指令 str 把暫存器內容存到棧上去 ldr  把棧上內容載入一暫存器中 .w是一個可選的指令寬度說明符。它不會影響為此指令的行為,它只是確保生成 32 位指令。Infocenter.arm.com的詳細資訊 bl 執行函式呼叫,並把使lr指向呼叫者(caller)的下一條指令,即函式的返回地址 blx 同上,但是在ARM和thumb指令集間切換。 bx  bx lr返回呼叫函式(caller)。
接下來是函式呼叫的一些規則。 一. 在iOS中你需要使用BLX,BX這些指令來呼叫函式,不能使用MOV指令(具體意義下面會說) 二. ARM使用一個棧來來維護函式的呼叫及返回。ARM中棧是向下生長(由高地址向低地址生長的)。 函式呼叫前後棧的佈局如圖一(引用的蘋果iOS ABI Reference):               圖(一) SP(stack pointer)指向棧頂(棧低在高地址)。棧幀(stack frame)其實就是通過R7及存在棧上的舊R7來標識的棧上的一塊一塊的儲存空間。棧幀包括:
  • 引數區域(parameter area),存放呼叫函式傳遞的引數。對於32位ARM,前4個引數通過r0-r3傳遞,多餘的引數通過棧來傳遞,就是存放在這個區域的。
  • 連結區域(linkage area),存放呼叫者(caller)的下一條指令。
  • 棧幀指標存放區域(saved frame pointer),存放呼叫函式的棧幀的底部,標識著呼叫者(caller)棧幀的結束及被呼叫函式(callee)的棧幀開始。
  • 區域性變數儲存區(local storage area)。用於存被調函式(callee)的區域性變數及在被呼叫函式(callee)結束後反回撥用函式(call)之前需要恢復的暫存器內容。
  • 暫存器儲存區(saved registers area)。Apple的文件中是這樣說的。但我認為這個區域和local storage area相鄰且乾的事也是存放需要恢復的暫存器內容,因此我覺得要不就把這個區域在概念上不區分出來,要不就把存放需要恢復的暫存器這項功能從local storage area中分出來。 當然這些都只是概念上的,其實實質上是沒有區別的。
接下來看看在呼叫子函式開始及結尾時所要做的事情。(官方叫序言和結語, prologs and epilogs) 呼叫開始:
  • LR入棧
  • R7入棧
  • R7 = SP地址。在經過前面兩條入棧指令後,SP指向的地址向下移動,再把SP賦值給R7, 標誌著caller棧幀的結束及callee的棧幀的開始
  • 將callee會修改且在返回caller時需要恢復的暫存器入棧。
  • 分配棧空間給子程式使用。由於棧是從高地址向低地址生長,所以通常使用sub sp, #size來分配。
呼叫結尾:
  • 釋放棧空間。add sp, #size指令。
  • 恢復所儲存的暫存器。
  • 恢復R7
  • 將之前存放的LR從棧上彈出到PC,這樣函式就返回了。