ARM体系结构支持7种处理器模式,分别是:用户、FIQ、IRQ、管理、中止(abort)、未定义和系统模式。除了用户模式外,其余都称之为特权模式。除了用户和系统模式外,其余都称之为异常模式
寄存器
ARM的寄存器分为两类, 普通寄存器和状态寄存器
普通寄存器总共16个,分别为R0-R15;状态寄存器共2个,分别为CPSR和SPSR寄存器(Reg)寄存器(APCS)作用域含义R0a1所有7种模式工作寄存器
R1a2所有7种模式..
R2a3所有7种模式..
R3a4所有7种模式..
R4v1所有7种模式必须保护
R5v2所有7种模式..
R6v3所有7种模式..
R7v4所有7种模式..
R8v5除FIQ模式..
R9v6除FIQ模式..
R10sl除FIQ模式栈限制
R11fp除FIQ模式帧指针
R12ip除FIQ模式内部过程调用寄存器
R13sp用户和系统模式栈指针
R14lr用户和系统模式连接寄存器
R15pc所有7种模式程序计数器
CPSR--
SPSR-除用户和系统模式-R13(sp): 每一种异常模式都有其自己独立的r13,它通常指向异常模式所专用的堆栈,也就是说五种异常模式、非异常模式(用户模式和系统模式),都有各自独立的堆栈,用不同的堆栈指针来索引。这样当ARM进入异常模式的时候,程序就可以把一般通用寄存器压入堆栈,返回时再出栈,保证了各种模式下程序的状态的完整性。
R14(lr): 每种模式下r14都有自身版组,它有两个特殊功能。保存子程序返回地址。使用BL或BLX时,跳转指令自动把返回地址放入r14中;子程序通过把r14复制到PC来实现返回,通常用下列指令之一:
当异常发生时,异常模式的r14用来保存异常返回地址,将r14如栈可以处理嵌套中断。
PS
ARM处理器中通常将寄存器R13作为堆栈指针(SP)。ARM处理器针对不同的模式,共有6个堆栈指针SP, 其中用户模式和系统模式共用一个SP,每种异常模式都有各自专用的R13寄存器(SP)。它们通常指向各模式所对应的专用堆栈,也就是ARM处理器允许用户程序有六个不同的堆栈空间。这些堆栈指针分别为R13、R13_svc、R13_abt、R13_und、R13_irq、R13_fiq.
汇编指令
存储器访问指令
ARM 处理是加载/存储体系结构的典型的RISC处理器,对存储器的访问只能使用加载和存储指令实现。ARM 的加载/存储指令是可以实现字、半字、无符/有符字节操作;批量加载/存储指令可实现一条指令加载/存储多个寄存器的内容,大大提高效率;SWP指令是一条寄存器和存储器内容交换的指令,可用于信号量操作等。
LDR和STR
加载/存储字和无符号字节指令。使用单一数据传送指令(STR 和LDR)来装载和存储单一字节或字的数据从/到内存。LDR 指令用于从内存中读取数据放入寄存器中;
STR 指令用于将寄存器中的数据保存到内存。1
2
3
4LDR{cond}{T} Rd, ;加载指定地址上的数据(字),放入Rd中
STR{cond}{T} Rd, ;存储数据(字)到指定地址的存储单元,要存储的数据在Rd中
LDR{cond}B{T} Rd, ;加载字节数据,放入Rd中,即Rd最低字节有效,高24位清零
STR{cond}B{T} Rd, ;存储字节数据,要存储的数据在Rd,最低字节有效其中,T 为可选后缀,若指令有T,那么即使处理器是在特权模式下,存储系统也将访问看成是处理器是在用户模式下。T在用户模式下无效,不能与前索引偏移一起使用T立即数1
2
3LDR R1,[R0,#0x12] ;将R0+0x12 地址处的数据读出,保存到R1中(R0 的值不变)
LDR R1,[R0,#-0x12] ;将R0-0x12 地址处的数据读出,保存到R1中(R0 的值不变)
LDR R1,[R0] ;将R0 地址处的数据读出,保存到R1 中(零偏移)
寄存器1
2LDR R1,[R0,R2] ;将R0+R2 地址的数据计读出,保存到R1中(R0 的值不变)
LDR R1,[R0,-R2] ;将R0-R2 地址处的数据计读出,保存到R1中(R0 的值不变)
寄存器及移位常数1
2LDR R1,[R0,R2,LSL #2] ;将R0+R2*4地址处的数据读出,保存到R1中(R0,R2的值不变)
LDR R1,[R0,-R2,LSL #2] ;将R0-R2*4地址处的数据计读出,保存到R1中(R0,R2的值不变)
数据处理指令
跳转指令
状态寄存器指令
ARM协处理器指令
示例分析
源代码1
2
3
4
5
6
7
8
9
10
11
12
13
14#include
int main(int argc, char* argv[])
{
int a = 1;
int b, c;
b = 3;
c = a + b;
printf("Hello c=%d!\n", c);
return 0;
}
编译:1arm-linux-gnueabihf-gcc hello.c -o hello --save-temp
汇编代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54.arch armv7-a
.eabi_attribute 28, 1
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 34, 1
.eabi_attribute 18, 4
.file"hello.c"
.text
.section.rodata
.align2
.LC0:
.ascii"Hello c=%d!\012\000"
.text
.align1
.globalmain
.syntax unified
.thumb
.thumb_func
.fpu vfpv3-d16
.typemain, %function
main:
@ args = 0, pretend = 0, frame = 24
@ frame_needed = 1, uses_anonymous_args = 0
push{r7, lr}
subsp, sp, #24
addr7, sp, #0
strr0, [r7, #4]
strr1, [r7]
movsr3, #1
strr3, [r7, #20]
movsr3, #3
strr3, [r7, #16]
ldrr2, [r7, #20]
ldrr3, [r7, #16]
addr3, r3, r2
strr3, [r7, #12]
ldrr1, [r7, #12]
movwr0, #:lower16:.LC0
movtr0, #:upper16:.LC0
blprintf
movsr3, #0
movr0, r3
addsr7, r7, #24
movsp, r7
@ sp needed
pop{r7, pc}
.sizemain, .-main
.ident"GCC: (Linaro GCC 7.3-2018.05) 7.3.1 20180425 [linaro-7.3-2018.05 revision d29120a424ecfbc167ef90065c0eeb7f91977701]"
.section.note.GNU-stack,"",%progbits@: 单行注释
参考