ARM处理器是英国Acorn有限公司设计的低功耗成本的第一款RISC微处理器。全称为Acorn RISC Machine。ARM处理器本身是32位设计,但也配备16位指令集,一般来讲比等价32位代码节省达35%,却能保留32位系统的所有优势。ARM公司是一个特别的公司,是一家CPU设计公司,ARM的经营模式在于出售其知识产权核(IP core),授权厂家依照设计制作出建构于此核的微控制器和中央处理器。最成功的实作案例属 ARM7TDMI,几乎卖出了数亿套内建微控制器的装置。还可以可以针对企业做定制版的CPU。
为什么移动端,嵌入式设备喜欢ARM架构的处理器:这是因为ARM CPU特点,体积小,高性能,低功耗,成本低。
由于节能的特点,ARM处理器非常适用于移动通讯领域,符合其主要设计目标为低耗电的特性。在加上成本低,所以在在移动端,ARM CPU的占用率高达99%。现在Intel从Core处理器也开始开始降功耗,但是不明显。
经典系列:ARM1 - ARM11,ARM8 以上是64位, 大部分ARM程序是32位程序。Cortex-A,智能手机端。 由于ARM CPU 普及率高,所以我们研究某种嵌入式设备软件的逆向,也变得简单了,这是后话。说了那么多ARM好,ARM棒,ARM顶呱呱的话,我们回到我们指令集,这才是我们关心的。
ARM指令集 ARM处理器可以支持3种指令集——ARM,Thumb和Jazelle
采用那种指令集,由cspr中的标志位来决定。大体说来: ◆ ARM——这是ARM自身的32位指令集 ◆ Thumb ——这是一个全16位的指令集,在16位外部数据总线宽度下,这个指令集的效率要比32位的ARM指令高一些。 ◆ Jazelle ——这是一个8位指令集,用来加速Java字节码的执行
ARM约定:
BYTE(字节): 8Bits
HalfWORD(半字): 16bits
WORD(字): 32bits
ARM流水线:
ARM处理器的指令属于定长指令,所以每个指令的取指,译码,周期都是一致的,除了指向周期可能不一致(大部分指令执行周期一致).
ARM的流水线是3级流水线,如下,
1 2 3
1 2 3
1 2 3
最先的ARM的流水线6级流水, 这样是为了解决指令同步问题。
ARM 寄存器
特殊的寄存器,在汇编中中,我们常有另外助记符
R15: PC => EIP
R14: LR => 链接寄存器,CALL指令存放返回地址,还是用栈
R13: SP => 堆栈指针
ARM寄存器:31个通用寄存器 6个状态寄存器
ARM 工作模式:
1、用户模式(Usr):用于正常执行程序;
2、快速中断模式(FIQ):用于高速数据传输;
3、外部中断模式(IRQ):用于通常的中断处理;
4、管理模式(svc):操作系统使用的保护模式;
5、数据访问终止模式(abt):当数据或指令预取终止时进入该模式,可用于虚拟存储以及存储保护;
6、系统模式(sys):运行具有特权的操作系统任务;
7、未定义指令中止模式(und):当未定义的指令执行时进入该模式,可用于支持硬件;
Arm的工作模式切换有两种方法:
被动切换:在arm运行的时候产生一些异常或者中断来自动进行模式切换
主动切换:通过软件改变,即软件设置寄存器来经行arm的模式切换,应为arm的工作模式都是可以通过相应寄存器的赋值来切换的。
Tips:当处理器运行在用户模式下,某些被保护的系统资源是不能被访问的。
除用户模式外,其余6种工作模式都属于特权模式;
特权模式中除了系统模式以外的其余5种模式称为异常模式;
大多数程序运行于用户模式;
进入特权模式是为了处理中断、异常、或者访问被保护的系统资源;
ARM汇编
arm汇编编译器: gun-as
ARM汇编帮助文档:http://sourceware.org/binutils/docs/as/index.html
一段ARM汇编代码的分析:
.arch armv5te
;.arch: 指定ARM架构版本
.fpu softvfp
;.fpu: 指定浮点运算的处理方法,softvfp:软件实现浮点与运算
.section.rodata
;.section: 定义一个节,rodata:只读数据节
.align2
;.align: 对齐单位2字节
.LC0:
.ascii"Hello World\000"
;.ascii:定义数据串
.text
.align2
.globalmain
;.global:声明一个全局符号main
.typemain, %function
main:
;定义main函数
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
stmfdsp!, {fp, lr}
;将fp,lr入展, 调用函数是,lr保存调用函数的返回地址
addfp, sp, #4
;将fp = sp+4,相当intel bp,用于访问参数和局部变量
subsp, sp, #8
;将sp = sp-8,申请函数内部局部变量空间
strr0, [fp, #-8]
;ARM 中函数调用约定,R0-R3,存储1-4的参数,多余4个参数,栈传参,
;str 指令,将寄存器的值存储到内存中, 将参数0存储在预留空间
strr1, [fp, #-12]
;将参数1存储在预留空间
ldrr3,.L2
.LPIC0:
addr3, pc, r3
;r3指向Helle World字符串
movr0, r3
;传参
blputs(PLT)
;调用函数puts, PLT:Procedure Linkage Table(相当于PE导入表)
movr3, #0
movr0, r3
;r0=0 返回值
subsp, fp, #4
;r0=0 回收函数内部局部变量空间
ldmfdsp!, {fp, pc}
; 1.还原非pc寄存器环境
; 2.pc = lr
.L3:
.align2
.L2:
.word.LC0-(.LPIC0+8)
;在地址L2处定义一个32位常量,常量值:.LC0-(.LPIC0+8),这个
.sizemain, .-main
.ident"GCC: (GNU) 4.6 20120106 (prerelease)"
.section.note.GNU-stack,"",%progbits