數據類型
跟高級語言很相似,ARM 支持對不同數據類型進行操作。
可以 load 和 store 的數據的類型分成:字(word),半字(halfwords)或字節(Byte)

無符號后綴:-h (無符號半字),-b (無符字節)
有符號后綴:-sh(有符號半子), -sb(有符號字節)
word(字)的有符號和無符號類型都是沒有后綴的
注:這里的后綴指的是 指令 的后綴,詳細看下面的 load/store 例子

有符號和無符號的區別:
- 有符號數據類型可以包含正值和負值,因此在范圍內較小。
- 無符號數據類型可以保存較大的正數 (包括 ' 0 ' ),但不能保存負數,因此范圍更廣。
這些例子是如何 load/store 數據
ldr = Load Word
ldrh = Load unsigned Half Word
ldrsh = Load signed Half Word
ldrb = Load unsigned Byte
ldrsb = Load signed Bytes
str = Store Word
strh = Store unsigned Half Word
strsh = Store signed Half Word
strb = Store unsigned Byte
strsb = Store signed Byte
字節序
字節序分成兩種:
現在有一個字符:ABCD 他們對應的 ascii 值是:0x41 0x42 0x43 0x44
小端序:Little-Endian (LE)
在小端序機器的內存中存儲着四個字母是:0x44434241
最低有效字節 LSB (least-significant-byte)為會放在低地址
大端序:Big-Endian (BE)
在小端序機器的內存中存儲着四個字母是:0x41424344
最高有效字節 MSB (most-significant-byte)放在低地址

可以看的出來這兩個的字節序不同之處在於對象的每個字節存儲在內存中的字節順序(byte-order),ARM 架構在 version 3 以前使用的是小端序(litter-endian),從 version 3 開始都是使用的大端序(big-endian),ARM 架構支持切換字節序,比如說在 ARMv6 上指令 固定是小端序 ,但是數據訪問可以是小端序,也可以是大端序,由程序狀態寄存器(CPSR) 的第 9 位 -- E 標志位控制。
ARM 寄存器
寄存器的數量取決於 ARM 的版本,ARM 參考手冊上寫的:除了 ARMv6-M 和 ARMv7-M 以外 ARM 架構有 30 個通用 32 位寄存器,前 16 個(r0-r15)可以在用戶模式(user-level mode)下使用,其他寄存器供特權模式下使用( ARMv6-M 和 ARMv7-M 除外)。在這里我們只會解接觸到 r0-r15
| # | 別稱 | 用途 |
|---|---|---|
| R0 | – | 通用寄存器 |
| R1 | – | 通用寄存器 |
| R2 | – | 通用寄存器 |
| R3 | – | 通用寄存器 |
| R4 | – | 通用寄存器 |
| R5 | – | 通用寄存器 |
| R6 | – | 通用寄存器 |
| R7 | – | 存放系統調用號 |
| R8 | – | 通用寄存器 |
| R9 | – | 通用寄存器 |
| R10 | – | 通用寄存器 |
| R11 | FP | 幀指針寄存器 |
| 特殊寄存器 | ||
| R12 | IP | 指令指針寄存器 |
| R13 | SP | 堆棧指針寄存器 |
| R14 | LR | 連接寄存器(存放返回地址) |
| R15 | PC | 程序計數器 |
| CPSR | – | 當前程序狀態寄存器 |
與 x86 架構的寄存器相關聯性的概覽
| ARM | Description | x86 |
|---|---|---|
| R0 | 通用寄存器 | EAX |
| R1-R5 | 通用寄存器 | EBX, ECX, EDX, ESI, EDI |
| R6-R10 | 通用寄存器 | – |
| R11 (FP) | 幀指針寄存器 | EBP |
| R12 | 內部程序調用寄存器 | – |
| R13 (SP) | 堆棧指針寄存器 | ESP |
| R14 (LR) | 連接寄存器(存放返回地址) | – |
| R15 (PC) | <- 程序計數器 /指令指針寄存器 -> | EIP |
| CPSR | 當前程序狀態寄存器 | EFLAGS |
r0-r12:可以在用來存放臨時數據或者地址
r0:可以充當算數運算的累加器,或者用於存放函數的返回值(像不像 x86 的 eax)
r7:在進行系統調用的時候用來存放系統調用號
r11:相當於 x86 的基址指針寄存器 ebp ,存放的是一個指向棧底的指針(因為棧是從高到低增長的,所以存的是棧的上邊界地址)
r13 (SP):始終指向棧頂,相當於 x86 中的堆棧指針寄存器 esp
r14 (LR):當調用函數時,連接寄存器會更新為調用函數初始化的指令的下一條指令的內存地址。這樣做允許程序在子函數調用結束后返回到父函數繼續執行
r15 (PC):程序計數器的每次的增量等於執行的指令的大小。這個大小在 ARM 下始終為 4 字節 ,在 Thumb 模式下始終為 2 字節,執行跳轉指令時,PC 保存目的地址。在執行分支代碼的過程中 PC 在 ARM 狀態下存儲當前指令的地址加 8(兩個 ARM 指令)的地址,在 Thumb(V1) 狀態下存儲當前指令加 4 (兩個 Thumb 指令)的地址。這與 x86 不同,在 x86 中,PC 總是指向要執行的下一條指令。
ARM 的函數調用約定:函數的前 4 個參數會放到 r0-r3
當前程序狀態寄存器(CPSR)
當前程序狀態寄存器 (CPSR) 是一個 32 為位寄存器用來保存處理器的狀態和控制信息
這個寄存器的作用相當於 x86 的 EFLAGS 寄存器
單個比特位的含義(省略了部分,詳細的可以看 這篇文章):
| Bits | 標志 | 描述 |
|---|---|---|
| 31 | N (Negative) | 指令運行結果為負數,則置 1 |
| 30 | Z (Zero) | 指令運行結果為 0 ,則置 1 |
| 29 | C (Carry) | 當運算結果導致進位,則置 1 |
| 28 | V (Overflow) | 如果指令的結果產生的值不能用 32 位的補碼表示,則置 1 |
| 24 | J (Jazelle) | 除了 ARM 和 Thumb 以外的第三種執行狀態,允許某些 ARM 處理器在硬件中執行 Java 字節碼 |
| 9 | E (Endian-bit) | 字節序控制位:置 0 時表示啟用小端序,置 1 時表示啟用大端序 |
| 5 | T (Thumb-bit) | ARM 模式下置 0,Thumb 模式下置 1 |
| 0-4 | M (Mode-bits) | 表示當前的 特權模式 |
CPSR 最高 4 位 N、Z、C、V,稱為條件碼標志。ARM 的大多數指令可以條件執行的,即通過檢測這些條件碼標志來決定程序指令如何執行。
假設現在用 cmp 指令來比較 1 和 2 ,cmp 會進行減法運算 1 - 2 = -1 結果為負數,這時這個運算結果就會影響到 CPSR 的 N 標志位,因為 cmp 的運算結果是負數所以會把 N 置為 1,如果是比較 2 和 2 運算結果是 0 這會置位 Z 標志位,但是要注意一點是 cmp 的執行結果不會影響它使用的寄存器只會 隱式 地影響 CPSR 寄存器的值
參考
via:https://azeria-labs.com/arm-data-types-and-registers-part-2/
