1. 程式人生 > 其它 >Arm入門第七講,Thumb 與ARM子程式。

Arm入門第七講,Thumb 與ARM子程式。

目錄

Arm入門第七講,Thumb 與ARM子程式。

一丶Thumb

1.1 什麼是Thumb

Thumb 指令集是16bit指令集,是為了相容資料匯流排寬度為16位的應用系統,Arm體系結構除了支援執行效率很高的32位Arm指令集以外,同時也支援16位的Thumb指令集。可以說Thumb是Arm指令集的一個子集,允許指令編碼為16位的長度。 與等價的32位程式碼相比較,Thumb指令集在保留32程式碼的優勢的同時,又大大節省了空間。

1.2 Thumb指令集的由來

Thumb指令集是從ARMV4T之後的ARM處理器有的指令集。是一種16bit指令模式,叫做Thumb. 他可以看做是ARM指令壓縮形式的子集,它是為減少程式碼量而提出,具有16bit的程式碼密度。

Thumb指令T恤並不完整,只支援通用功能,必要時仍然需要ARM指令。 比如進入異常。

1.3 Thumb的特點

1.Thumb程式碼所需要的儲存空間為Arm程式碼的 60%-70% 畢竟指令短,那麼自然就會佔用空間。

2.Thumb程式碼使用的指令數比ARM程式碼多30%--40%

3.若使用32位的儲存器,那麼ARM程式碼比Thumb程式碼塊40%

4.若使用16位儲存器,Thumb則比ARM程式碼快40%-50%

5.與ARM程式碼比較,使用Thumb程式碼,儲存器的功耗會降低30%

顯然是各有優缺點的。

1.4 Thumb與Arm的卻別

區別如下:

1. 分支指令: 跳轉的範圍小,除了B指令外,其他都是無條件跳轉。
2. 資料處理指令: Thumb指令只有兩個運算元,而ARM指令則是3個運算元。
3. 單暫存器載入/儲存指令: Thumb指令只能訪問R0-R7暫存器。
4. 多暫存器載入/儲存指令: Thumb指令只能訪問R0-R7的子集
5. Thumb特有指令: push 和POP是它特有的指令,作用於R13(sp)暫存器。

編寫Thumb 指令的時候,要先使用偽指令CODE16宣告,而且在ARM指令中要使用BX

指令來跳轉到Thumb指令,BX的指令地址低位為1則是表示THUMB指令,否則就是ARM指令。

編寫ARM指令的時候可以用 CODE32宣告,然後如果遵循一定的呼叫規則,則Thumb子程式和ARM子程式可以互相呼叫。

二丶ARM的ATPCS呼叫標準

ATPCS標準 可以理解為ARM是怎麼使用堆疊的。

那麼在此之前需要熟悉 呼叫約定的知識。 X86的棧操作知識等等。

2.1 呼叫約定

呼叫約定分為如下:

  • cdecl呼叫約定

    該呼叫約定遵循以下規則:

    引數入棧順序是從右向左

    棧平衡負責 是由呼叫者來平。

    如函式A 呼叫函式B 在這裡A就是呼叫者 B就是被呼叫者。

  • stdcall 呼叫約定

    入棧規則: 引數從右向左入棧

    棧平衡負責: 被呼叫者負責

    如B函式接受2個引數。 A呼叫B 在B執行完畢之後會操作棧來保證棧平衡。

  • fastcall呼叫約定

    引數入棧順序: 函式的第一第二個引數通過ecx和edx入棧。 x64的結構下還有r8 r9(暫存器), 剩餘的引數則從右向左入棧。

    棧平衡:被呼叫者進行棧平衡。 (如果是x64那麼則是呼叫者負責)

返回值的存放:

​ 返回值放在EAX和RAX(x64)中

下面是呼叫堆疊圖:

2.2 ARM呼叫約定

ARM函式之間互相呼叫遵循的規則就是ATPCS(ARM-THUMB Procedure Call Standard) ATPCS主要是定義了函式呼叫時引數的傳遞規則以及函式的返回規則。 它很類似於X64架構下的fastcall呼叫。

它們有一個共同的特點就是暫存器多,有大量暫存器可用。

  • 傳參方式

    R0 -R3是傳遞函式的第1到第四個引數的,超出的部分從右向左通過棧傳遞。

    在X64下再是 RCX RDX R8 R9暫存器進行引數傳遞。所以這裡很雷同。

  • 棧平衡

    ​ 棧平衡則是由呼叫者進行棧平衡的。

  • 結果儲存

    1.結果為32位整數的時候,可以通過暫存器R0來返回。

    2.結果是64位整數的時候,可以通過R0 R1返回。

    3.結果是浮點數,那麼通過浮點暫存器F0 D0 或者S0返回。

    4.結果是符合浮點數,那麼可以通過暫存器F0 -FN 或者D0 -DN來進行返回。

  • 區域性變數

    R4-R11是用來儲存區域性變數的,如果用到了那麼函式在進入的時候就要先儲存,這點類似於x86環境下的pushad pushfd等指令,儲存暫存器環境。 而在返回的時候,這些暫存器的值也要進行恢復。

    Thumb指令只能使用R4-R7,R11也可以做FP暫存器。也就是x86的EBP

  • 返回地址

    返回地址使用R14暫存器進行儲存(也叫做LR暫存器)

    x86的返回地址在棧中儲存。

  • 棧頂暫存器

    ​ R13是作為棧頂暫存器的,也就是SP暫存器。 x86下則是使用ESP

  • 棧基址暫存器

    ​ R11作為棧基址暫存器的 也就是FP指令。 x86下則是EBP

  • 下一條指令暫存器

    R15暫存器,也叫做PC暫存器。 是指向下一條要執行指令的,類似於X86下的EIP暫存器。

  • 備份暫存器

    ​ R12暫存器主要作用於子程式內部的,也叫做IP暫存器。 內部過程呼叫暫存器,可以備份儲存 SP(R13) LR(R14)暫存器等。

堆疊使用的FD滿遞減棧,也就是跟X86是一樣的。