算术运算:
ADD
ADC
SUB
带借位的减法:SBC R0,R1,R2 ;R0=R1-R2-!C
逆向减法指令:RSB R0,R1,R2 ;R0=R2-R1
带借位的逆向减法指令:RSC R0,R1,R2 ;R0=R2-R1-!C
逻辑运算指令:
AND:可以用来清零相应的位
ORR:可以用来置位相应的位
EOR:可以用来反转操作数1的某些位
BIC:可以用来清除相应的位
比较指令:
CMP:比较指令,该指令实际上是进行一次减法运算,但不存储结果,只更改条件标识
CMN:反值比较指令,该指令实际上是将操作数Rn和操作说oprand相加,然后更改条件标识
TST:位测试指令(TST指令用于把一个寄存器Rn的内容和另一个操作数operand2按位 进行与运算,并根据运算结果更新CPSR中条件标志位的值)
TEQ:相等测试指令(TEQ指令用于把一个寄存器Rn的内容和另一个操作数operand2按 位进行异或运算,并根据运算结果更新CPSR中条件标志位的值。
该指令通常用于比较操作数Rn和操作数Operand2是否相等)
乘法指令:
MUL:32位乘法指令
MLA:32位乘加指令
SMULL:64位有符号数乘法指令 SMULL R0,R1,R2,R3
;R0=(R2*R3)的低32位
;R1=(R2*R3)的高32位
SMLAL:64位有符号数乘加指令 SMLAL R0,R1,R2,R3
;R0=(R2*R3)的低32位+R0
;R1=(R2*R3)的高32位+R1
UMULL:64位无符号数乘法指令
UMLAL:64位无符号数乘加指令
交换指令:
SWP:字数据交换指令
SWPB:字节数据交换指令
SWP R0,R1,[R2]
;将R2所指向的存储器中的字数据加载到R0,同时将R1中的子数据存储到R2所指向的存储单元
SWPB R0,R1,[R2]
;将R2所指向的存储器中的字节数据加载到R0中,R0的高24位清零,同时将R1的低8位数据存储到R2所指向的存储单元
当R0和R1为一个寄存器时(R1=R0),则可以互换R0与R2中的数据
分支指令:
B:分支指令
BL:带返回的分支指令,在跳转之前将PC的当前内容复制到R14(LR)中保存
BX:带状态切换的分支指令,BX Rm;Rm时一个表达目标地址的寄存器,当Rm中的最低位Rm【0】为1时,强制程序从ARM指令状态跳到Thumb指令状态。反之亦然。
BLX:带返回和状态切换的分支指令
程序状态寄存器访问指令:
MRS Rd,psr ;读状态寄存器的指令,Rd<----psr
MSR psr,Rd ;写状态寄存器指令,psr<----Rd
软件中断指令:
SWI:软件中断指令,以便用户程序能调用操作系统的系统例程
当执行SWI调用时,ARM处理器将会实现下列操作:
1,把中断处的地址值(pc-4)复制到R14中,保留中断处地址
2,把CPSR复制到SWI模式的SPSR,保存状态寄存器
3,把状态寄存器的其他模式改变成管理模式
4,把中断向量0X00000008赋值给PC
5,禁止IRQ中断,使CPSR[7]=1
ARM协处理器:
ARM微处理器可支持多达16个协处理器,用于各种协处理操作,在程序执行的过程中,每个协处理器只执行针对自身的协处理指令,忽略ARM处理器和其他协处理器的指令。
ARM的协处理器指令主要用于ARM处理器初始化ARM协处理器的数据处理操作,以及在ARM处理器的寄存器和协处理器的寄存器之间传送数据,和在ARM协处理器的寄存器和存储器之间传送数据。ARM协处理器指令包括以下5条:
CDP:协处理器数据处理指令
LDC:协处理器数据加载指令
STC:协处理器数据存储指令
MCR:ARM处理器寄存器到协处理器寄存器的数据传送指令
MRC:协处理器寄存器到ARM处理器寄存器的数据传送指令
符号定义伪操作:
用于定义全局变量的GBLA(全局数字变量),GBLL(全局逻辑变量),GBLS(全局字符串变量).
用于定义局部变量的LCLA,LCLL,LCLS
用于对变量进行赋值的SETA,SETC,SETS
为通用寄存器列表定义名称的RLIST
数据定义伪操作:
DCB:分配一片连续的字节存储单元并初始化
DCD:分配一片连续的字存储单元并初始化
DCW:分配一片连续的半字存储单元并初始化
SPACE:分配一片连续的存储单元
用于分配一片连续的存储区域并初始化为0
FIELD:定义一个结构化的内存表的数据域,可以用#来代替
MAP:定义一个结构化的内存表首地址,可以用^来代替
FIELD和MAP伪操作配合使用来定义结构化的内存表。
MAP 0X100
A FIELD 4
B FIELD 4
S FIELD 16
LTORG:定义一个数据缓冲池的开始
EXPORT伪操作用于在程序中生命一个全局的标号,该标号可在其他的文件中引用。
ImPORT:伪操作用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用,而且无论当前源文件是否引用该标号,该标号均会被加入到当前源文件的符号表中
GET:伪操作作用于讲一个源文件包含到当前的源文件中,并将被包含的源文件在当前位置进行汇编处理
INCBIN:伪操作用于将一个目标文件或数据文件包含到当前的源文件中,被包含的文件不做任何变动地存放在当前文件中。
异常中断编程:
ARM的异常中断:复位,未定义指令,软件中断,指令预取中止,数据中止,中断请求(IRQ),快速中断请求(FIQ)
快速请求(IRQ):IRQ属于正常的的中断请求,可通过对处理器的nIRQ引脚输入低电平产生,IRQ的优先级低于FIQ,当程序执行进入FIQ异常时,IRQ可能被屏蔽
若将CPSR的 I 位置位1,则会禁止IRQ中断,若将CPSR的I位清零,处理器会在指令执行完之前检查IRQ的输入
快速中断请求(FIQ):
FIQ和IRQ中断处理机制:
FIQ异常中断位快读异常中断,它比IRQ异常中断优先级高,主要表现在下面两个方面:
1,当FIQ和IRQ异常中断同时产生时,CPU先处理FIQ异常中断
2,在FIQ异常中断处理程序中IRQ异常中断被禁止
ARM异常中断的处理过程:
1,保存处理器当前状态,中断屏蔽位以及各种条件标志位
SUB LR,LR,#4 ;保存中断的返回地址
STMFD SP!, {LR}
MRS R14, SPSR ;保存状态寄存器,及其他工作寄存器
STMFD SP!, {R12,R14}
2,设置当前程序状态寄存器CPSR中相应的位
2.1,改变处理器状态进入ARM状态
2.2,改变处理器模式进入相应的异常模式
2.3,设置中断禁止位禁止相应中断
不管一场发生在ARM还是Thumb状态下,处理器都将自动进入ARM状态,如果此时处理器处于Thumb状态,则当异常向量地址加载入PC时,处理器自动切换到ARM状态,设置CPSR中的位,使得处理器进入相应的执行模式
典型的代码:
MRS R14,CPSR
BIC R14,R14,#0X9F
ORR R14,R14,#0X1F
MSR CPSR_c, R14
3,保存返回地址
将下一条指令的地址存入LR寄存器中,以便程序在处理一场返回是能从正确的位置重新开始执行。
典型代码:
STMFD SP!, {R0-R3,LR}
4,执行中断处理程序
强制PC从相关的异常向量地址去下一条指令执行从而跳转到相应的异常处理程序处
典型代码:
BL C_irq_handler
异常中断的返回:
1,恢复通用寄存器中的值,通用寄存器的恢复采用一般的堆栈操作指令
2,恢复状态寄存器的值,恢复被中断程序的的处理器状态,将SPSR_mode寄存器内容复制到当前程序状态寄存器CPSR中
3,修改PC的值
其中后两条可以采用:
MOVS PC, LR
SUBS PC, LR,#4
LDMFD sp!, {pc}^
在特权模式下,“S”和“^”的作用就是使指令在执行时,同时完成从SPSR到CPSR中的复制,达到恢复状态寄存器的作用
中断后的返回指令:
未定义指令: MOV PC, R14_und
软件中断: MOV PC, R14_svc
取值中断: SUBS PC, R14_abt,#4
数据中止: SUBS PC,R14_abt,#8
IRQ: SUBS PC,R14_irq,#4
FIQ: SUBS PC,R14_fiq,#4
指令的条件执行:
当处理器工作在ARM状态是,几乎所有的指令都根据CPSR中条件码的状态和指令的条件域有条件地执行,下面给出条件码:
我们注意到条件标志位位于CPSR状态寄存器中,下面给出CPSR寄存器的说明:
(图片截于刘洪涛,讲师的讲课稿)
结合以上两个图,我们对于ARM中条件执行也就有了很好的认识了!
现在我们来分析一个简单的软件中断的例子:
SWI异常中断处理程序:下面是完成它的步骤(在存储寄存器 r0-r12 之后):
- 它从 r14 中减去 4 来获得 SWI 指令的地址。
- 把这个指令装载到一个寄存器。
- 清除这个指令的高端 8 位,去掉了 OpCode 而只剩下的 SWI 编号。
- 使用这个值来找到要被执行的代码的例程的地址(使用查找表等)。
- 恢复寄存器 r0-r12。
- 使处理器离开超级用户模式。
- 跳转到这个例程的地址。
T_bit EQU 0x20
SWI_Handler
STMFD sp!, {r0-r3,r12,lr}
MOV r1, sp
;寄存器压栈,设置堆栈指针
MRS r0, spsr
STMFD sp!, {r0}
;取出 spsr 并压栈保存
;TST指令用于把一个寄存器Rn与oprand2进行与操作,并根据结果更新状态寄存器CPSR
TST r0, #T_bit
LDRNEH r0, [lr,#-2] ;H的后缀表示是半字操作,因为Thumb是 ;16位的
BICNE r0, r0, #0xff00
LDREQ r0, [lr,#-4]
BICEQ r0, r0, #0xff000000
;测试状态
; r0 now contains SWI number
; r1 now contains pointer to parameters on stack
BL C_SWI_Handler
LDMFD sp!, {r1}
MSR spsr_csxf, r1
LDMFD sp!, {r0-r3,r12,pc}^ 恢复寄存器并返回