部分內容摘自Failwest大牛的《0day安全》第二版,侵刪
ARM處理器共有37個寄存器,被分為若干個組,這些寄存器包括:
- 31個通用寄存器,包括未分組寄存器R0-R7、分組寄存器R8-R14和程序計數器( PC 指針),均為32位的寄存器。
- 6個狀態寄存器,包括程序狀態寄存器 CPSR 和5個物理狀態寄存器 SPSR (用以異常發生時保存 CPSR 的值,異常退出時恢復 CPSR )。 這些狀態寄存器用以標識 CPU 的工作狀態及程序的運行狀態,均為32位。
具體如下表所示:
用戶模式 usr | 系統模式 sys | 特權模式 svc | 中止模式 abt | 未定義指令模式 und | 外部中斷模式 irq | 快速中斷模式 fiq |
---|---|---|---|---|---|---|
R0 | R0 | R0 | R0 | R0 | R0 | R0 |
R1 | R1 | R1 | R1 | R1 | R1 | R1 |
R2 | R2 | R2 | R2 | R2 | R2 | R2 |
R3 | R3 | R3 | R3 | R3 | R3 | R3 |
R4 | R4 | R4 | R4 | R4 | R4 | R4 |
R5 | R5 | R5 | R5 | R5 | R5 | R5 |
R6 | R6 | R6 | R6 | R6 | R6 | R6 |
R8 | R8 | R8 | R8 | R8 | R8 | R8_fiq |
R9 | R9 | R9 | R9 | R9 | R9 | R9_fiq |
R10 | R10 | R10 | R10 | R10 | R10 | R10_fiq |
R11 | R11 | R11 | R11 | R11 | R11 | R11_fiq |
R12 | R12 | R12 | R12 | R12 | R12 | R12_fiq |
R13(SP) | R13 | R13_svc | R13_abt | R13_und | R13_inq | R13_fiq |
R14(LR) | R14 | R14_svc | R14_abt | R14_und | R14_inq | R14_fiq |
PC(R15) | PC | PC | PC | PC | PC | PC |
CPSR | CPSR | CPSR | CPSR | CPSR | CPSR | CPSR |
SPSR_svc | SPSR_abt | SPSR_und | SPSR_inq | SPSR_fiq |
未分組寄存器 R0 - R7:
對于未分組寄存器,它們沒有被系統用于特別的用途,因此任何可采用通用寄存器的應用場合都可以使用未分組寄存器。
但需要注意一點,未分組寄存器不會因為處理器模式的改變而更改指向的寄存器,因此在所有的處理器模式下未分組寄存器都指向同一個寄存器,當中斷或異常處理造成處理器模式轉換的時候,由于不同的處理器模式使用了相同的物理寄存器,這就有可能造成寄存器中的數據被破壞。
(關于工作模式和狀態可以移步至我的另一篇文章: ARM狀態結構小記 )
分組寄存器 R8 - R14
對于分組寄存器,它們每一次所訪問的物理寄存器和處理器當前的運行模式有關。例如在快速中斷模式 fiq下R8-R12訪問寄存器 R8_fiq-R12_fiq ;而在其他模式下又訪問 R8_usr-R12_usr 。因此它們每個對應著兩個不同的寄存器。
對于R13(SP)、R14(LR)來說,每個寄存器對應著6個不同的物理寄存器,其中的一個是用戶模式與系統模式共用,另外5個物理寄存器對應于其他5種不同的運行模式。采用以下的記號來區分不同的物理寄存器:
R13_< mode >
R14_< mode >
其中,mode為以下幾種模式之一:usr、fiq、irq、svc、abt、und。
R13(SP)
寄存器 R13 在 ARM 指令還有著一個非常重要的作用,通常他被用作堆棧指針,當然這只是一種習慣用法,用戶也可以使用其他的寄存器作為堆棧指針,但在Thumb指令集中,某些指令強制性地要求使用R13作為堆棧指針。
由于處理器的每種運行模式均有自己福利的物理寄存器R13,使其指向該運行模式下的棧空間,這樣,當程序的運行進入異常模式時,可以將需要保護的寄存器放入R13所指向的堆棧,而當程序從異常模式返回時,則從對應的堆棧恢復,采用這種方式可以保證異常發生后程序的正常執行。
R14(LR)
R14 也稱作子程序連接寄存器(Subroutine Link Register)或連接寄存器 LR 。當執行 BL 子程序調用指令時,R14 中得到 R15 (程序計數器PC)的備份。
0x00008d68 <+44>: bl 0x8cd4 <func>
0x00008d6c <+48>: ...
0x00008d70 <+52>: ...
通常情況下,在匯編代碼中不會出現 R14 中產生 PC 備份的指令語句。可以簡單的理解為在執行調用的同時,將當前 PC 的指向的值 0x00008d70 減去一條指令的長度,這里是ARM工作狀態,指令長度為 0x00000004,并交由R14保存。減去一條指令的原因很簡單,不減的話返回的時候中間 0x00008d6c 處的那條指令就被跳過了。:-p
(當前執行的是 0x00008d68 處的指令,0x00008d6c 處的指令處于譯碼階段,0x00008d70 的指令處于取指階段,PC總是指向取指階段的指令。關于 ARM 處理器的流水線機制和 PC 指向的值 詳見下文。)
其他情況下,R14 也可以用作通用寄存器。與之類似,當發生中斷或異常時,對應的分組寄存器 R14_svc、R14_irq、R14_fiq、R14_abt 和 R14_und 用來保存 R15 的返回值。
每一種處理器模式在自己的物理 R14 中存放當前子程序的返回地址。當通過BL、BX 等指令調用子程序時,R14就被設置成該子程序的返回地址。例如有匯編指令如下:
- 執行以下任意一條指令:
MOV PC,LR
BX LR
- 在子程序入口處使用以下指令將R14存入堆棧:
STMFD SP!,{<Regs>,LR}
- 對應的,使用以下指令可以完成子程序返回:
LDMFD SP!,{<Regs>,PC}
當發生異常中斷的時候,該模式下的特定物理R14被設置成該異常模式將要返回的地址。
R15(PC)
介紹R15之前先簡單了解一下 ARM 處理器的是流水線機制。 ARM7 處理器采用3級流水線來增加處理器指令流的速度,能提供 0.9MIPS/MHz 的指令處理速度。
ARM7 的流水線有3個階段,因此指令分3個階段執行。
⑴ 取指從存儲器裝載一條指令
⑵ 譯碼識別將要被執行的指令
⑶ 執行處理指令并將結果寫會寄存器
對于x86處理器來說,只有完成一條指令的讀取和執行后,才會執行下一條指令。這樣, PC 始終指向的正在“執行”的指令。
而對于 ARM7 來說因為是3級流水線,所以把指令的處理分為了上面所述的3個階段。所以處理時實際是這樣的: ARM 正在執行第1條指令的同時對第2條指令進行譯碼,并將第3條指令從存儲器中取出。因此 ARM7 流水線只有在取第4條指令時,第1條指令才算完成執行。繼而 ARM 的 PC 寄存器永遠指向當前執行的指令后的第二條指令,即處于取指階段的指令。
另外,在ARM狀態下,最低的兩位[1:0]為0,其他位[31:2]用于保存PC;在Thumb狀態下,最低位[0]為0,其他位 [31:1]用于保存PC;所以 R15(PC)雖然可以用作通用寄存器,但是有一些指令在使用R15時有一些特殊限制,當違反了這些限制時,程序的執行結果是未知的。
R16(CPSR)
寄存器R16用作當前程序狀態寄存器 CPSR (Current Program Status Register),可在任何運行模式下被訪問,它包括條件標志位、中斷禁止位、當前處理器模式標志位,以及其他一些相關的控制和狀態位。
每一種運行模式下又都有一個專用的物理狀態寄存器,稱為備份的程序狀態寄存器 SPSR (Saved Program Status Register),當異常發生時, SPSR 用于保存 CPSR 的當前值,從異常退出時則可由 SPSR 來恢復 CPSR 。
由于用戶模式和系統模式不屬于異常模式,他們沒有 SPSR ,當在這兩種模式下訪問 SPSR ,結果是未知的。
執行條件標志位
ARM 的執行條件與 x86 下面的標志位有些類似,系統通過對這些標志位的判斷來確定是否滿足執行條件。幾乎所有的 ARM 指令都包含一個4位的條件碼,位于指令的最高4位。條件碼共有16種,每種條件碼可用兩個字符表示,這兩個字符可以添加在指令助記符的后面和指令同時使用。
例如,跳轉指令 B 可以加上后綴 EQ 變成 BEQ 表示“相同則跳轉”,即當 CPSR 中的Z標志置位時發生跳轉。在16種條件標志碼中,只有15種可以使用,如下表所示。第十六種(1111)為系統保留,暫時不能使用。
編 碼 | 條件助記符 | 標志位 | 含 義 |
---|---|---|---|
0000 | EQ | Z=1 | 相等 |
0001 | NE | Z=0 | 不相等 |
0010 | CS | C=1 | 無符號大于或等于 |
0011 | CC | C=0 | 無符號小于 |
0100 | MI | N=1 | 負值 |
0101 | PL | N=0 | 正值或 0 |
0110 | VS | V=1 | 溢出 |
0111 | VC | V=0 | 無溢出 |
1000 | HI | C=1 且 Z=0 | 無符號大于 |
1001 | LS | C=0 且 Z=1 | 無符號小于或等于 |
1010 | GE | N 和 V 相同 | 有符號大于或等于 |
1011 | LT | N 和 V 不相同 | 有符號小于 |
1100 | GT | Z=0 且 N 等于 V | 有符號大于 |
1101 | LE | Z=1 且 N 不等于 V | 有符號小于或等于 |
1110 | AL | 任意 | 無條件執行(不推薦使用) |
1111 | NV | 任意 | 從不執行(不要使用) |