六、ARM指令集:
1、数据操作指令:
(1)MOV 将数据从一个寄存器传送到另一个寄存器:
MOV AX,2000H;将16位数据2000H传送到AX寄存器
MOV AL,20H;将8位数据20H传送到AL寄存器
MOV AX,BX;将BX寄存器的16位数据传送到AX寄存器
MOV AL,[2000H];将2000H单元的内容传送到AL寄存器
MOVW 把 16 位立即数放到寄存器的底16位,高16位清0
MOVT 把 16 位立即数放到寄存器的高16位,低 16位不影响
movw r8, #19028 ; 0x4a54
movt r8, #49456 ; 0xc130
r8 = 0xc1304a54
(2)AND将寄存器做“逻辑与”操作后保存结果到其他寄存器
AND R2,R1,R3 // R2 = R1 & R3
ANDS R0,R0,#0x01 // R0 = R0 & 0x01
(3)SUB
SUB R0,R1,R2 //R0 = R1 – R2
SUB R0,R1,#256 //R0 = R1 -256
(4)ADD
ADD R0,R1,R2 //R0 = R1 + R2
ADD R0,R1,#256 //R0 = R1 + 256
ADD R0,R2,LSL#1 //R0 = R2 + (R3 << 1)
(5)CMP比较指令
(6)BIC位清零指令
BIC R0,R0,#0x1011 //清除位 0/1/3
2、乘法指令:
MUL MLA
MUL R1,R2,R3 //R1 = R2 * R3
MOV R0,#0x0A
MLA R1,R2,R3,R0 // R1 = R2 * R3 + 10
3、Load/Store指令:
(1)LDR从存储器中将一个32位的字数据传送到目的寄存器中。
LDR R1,[R0,#0x12] //将R0 +12地址处的数据读出,保存到R0中;
LDR R1,[R0,R2] //将R0 + R1地址的数据读出,保存到R1中;
LDR RD,[Rn],#0x04 //Rn的值用作传输数据的基地址,在数据传送后,将偏移量0x04与Rn相加写回到Rd中
LDR R0,[R1,LSL #3] ;将存储器地址为R1*8的字数据读入寄存器R0。
LDR R0,[R1,R2,LSL #2] ;将存储器地址为R1+R2*4的字数据读入寄存器R0。
LDR R0,[R1,,R2,LSL #2]! ;将存储器地址为R1+R2*4的字数据读入寄存器R0,并将R1+R2*4的值存入R1。
(2)STR 用于将一个32bit的数据写入到指定的内存单元
STR R0,[R1],#8 //将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。
STR R0,[R1,#8] //将R0中的字数据写入以R1+8为地址的存储器中
STR R1, [R0] //将r1寄存器的值,传送到地址值为r0的(存储器)内存中
4、跳转指令:
B 跳转指令
BL 带返回的连接跳转
BX 跳转并切换状态
BLX 带返回的跳转并切换状态
5、状态操作指令:
ARM指令提供了两条如下指令,可直接控制程序状态寄存器(只有在特权模式下才能修改状态寄存器):
(1)MRS: 把程序状态寄存器的值送到一个通用寄存器中
MRS R1, CPSR //将CPSR状态寄存器读出,保存到R1中
MRS R2, SPSR
(2)MSR:把寄存器的内容传送到程序状态寄存器
MSR CPSR_c,#0xD3 //CPSR[7:0] = 0xD3切换到管理模式
MSR CPSR_c,R3 //CPSR = R3
6、异常产生指令:
SWI:软中断指令,产生软中断,处理器进入管理模式;
SWI 0 //产生软中断,中断立即数为0
SWI 0x123456 //产生软中断,中断立即数为0x123456
BKPT:断点中断指令,处理器产生软件中断;
产生一个预取异常,用来设置软件断点;
七、ARM指令的寻址方式:
1、立即数寻址:
MOV R0,#0 //送0到R0中
ADD R3,R3,#1 //R3的值加1
CMP R7,#1000 //R7的值和1000比较
BIC R9,R8,#0xff00 //将R8中8~15位清0,结果保存在R9中
2、寄存器寻址:
寄存器的值可以被直接用于数据操作指令
MOV R2,R0 //R0的值送R2
ADD R4,R3,R2 //R4 = R2 + R3
CMP R7,R8 //比较R7和R8的值
3、寄存器移位寻址:
预处理和移位发生在同一周期内,有效使用移位寄存器,可以提供代码执行效率;
ADD R2,R0,R1,LSR #5
MOV R1,R0,LSL #2
RSB R9,R5,R5,LSL #1
SUB R1,R2,R0,LSR #4
4、寄存器间接寻址:
LDR R1,[R2] //将R2的数值作为地址,取出地址中的数据保存到R1中
STR R1,[R2] //将R2数值作为地址,取出R1中的值存入R2所指向的地址
5、基址变址寻址:
基址变址是将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址;
基址变址寻址常用于查表、数组操作、访问基址附近的存储单元等。
LDR R1,[ R0,#0xf ] //将R0的数值加0x0f作为地址,取出此地址的数值保存到R1
STR R1,[R0,#-2] //将R0的数值减2作为地址,将R1中的内容保存到此地址中
STR R1,[R0,+R2] //将R0的值加上R2的值作为地址,把R1的内容保存到该地址
6、多寄存器寻址/块拷贝寻址:
批量Load、Store指令将一片连续的内存单元数据加载到通用寄存器组中,或将一组通用寄存器的数据存储
到内存单元中:
IA :后递增方式
IB :先递增方式
DA:后递减方式
DB:先递减方式
块拷贝寻址指令:
STMIA
STMIB
7、相对寻址:
BL FUN1 //调用到FUN1的子程序
B LOOP //条件跳转到LOOP标号处
STMDA
STMDB
八、异常中断
1、硬件中断&软件中断:
硬件中断是随机的,不可预测的
软件中断是事先安排的(如workQueue、task)
2、ARM处理器有七种类型的异常::
(1)复位异常(Reset):处理器在工作时, 突然按下重启键, 就会触发该异常;
(2)数据异常(Data Abort):读取数据失败;
(3)快速中断异常(FIQ):快速中断要比普通中断响应速度要快一些;
(4)外部中断异常(IRQ):普通中断;
(5)预取异常(Prefetch Abort):预取指令失败, ARM 在执行指令的过程中, 要先去预取指令准备执行,
如果预取指令失败, 就会产生该异常;
(6)软中断异常(SWI):软件中需要去打断处理器工作, 可以使用软中断来执行 ;
(7)未定义指令异常(Undefined Instruc
tion):处理器无法识别指令的异常, 处理器执行的指令是有规范的,
如果尝试执行不符合要求的指令, 就会进入到该异常指令对应的地址中;
当异常发生时,分组寄存器R14和SPSR用于保存处理器状态,
异常返回时,SPSR内容恢复到SPSR,链接寄存器R14的内容恢复到程序计数器PC。
下图中每种异常对应一种内核的工作模式,当然每种异常产生,内核都会进入特定的工作模式;
3、异常处理流程:
(1)中断响应所做的工作:
A、保存短点:保存下一将要执行的指令的地址,也就是把这个地址送入堆栈;
B、寻找中断入口:根据不同的中断源产生的中断,查找不同的入口地址;
C、执行中断处理程序;
D、中断返回:执行完中断指令后,就从中断返回到主程序继续执行;
(2)异常向量表
每一个异常发生时,总是从异常向量表开始跳转,所谓的异常向量表,是指由7个异常向量及其处理函数跳转
关系组成的表:
0x00000000: b reset
0x00000004: ldr pc, _undefined_instruction
0x00000008: ldr pc, _software_interrupt
0x00000008: ldr pc, _software_interrupt
0x0000000c: ldr pc, _prefetch_abort
0x00000010: ldr pc, _data_abort
0x00000014: ldr pc, _not_used //保留
0x00000018: ldr pc, _irq
0x0000001c: ldr pc, _fiq
(3)当一个ARM异常返回时,需要完成如下任务:
通用寄存器的恢复;
状态寄存器的恢复;
PC指针的恢复;