STR R1,[R0,#0x04] ;将R1的数据存储到 R0+0x04存储单元,R0的值不变 (若有!,则R0就要更新)
LDRB R3,[R2],#1 ;读取R2地址上的一字节数据并保存到R3中,R2=R2+1 STRH R1,[R0,#2]! ;将R1的数据保存到R0+2的地址中,只存储低2字节数据,R0 =R0+2
LDM和STM是批量加载/存储指令,LDM为加载多个寄存器,STM为存储多个寄存器,主要用途是现场保护,数据复制、参数传递等,其模式有8种,前4种用于数据块的传输,后4种用于堆栈操作 IA:每次传送后地址加4 IB:每次传动前地址加4 DA:每次传送后地址减4 DB:每次传送前地址减4 FD:满递减堆栈 ED:空递增堆栈 FA:满递增堆栈 EA:空递增堆栈
批量加载/存储指令举例如下:
LDMIA R0!,{R3-R9} ;加载R0指向的地址上的多字数据,保存到R3-R9中,R0值更新
STMIA R1!,{R3-49} ;将R3-R9的数据存储到R1指向的地址上,R1值更新 STMFD SP!,{R0-R7,LR} ; 现场保存,将R0~R7、LR入栈 LDMFD SP!,{R0-R7,PC}^ ;恢复现场,异常处理返回
使用LDM/STM进行数据复制
LDR R0,=SrcData ;设置源数据地址,LDR此时作为伪指令加载地址要加 = LDR R1,=DstData ;设置目标地址
LDMIA R0,{R2-R9} ;加载8字数据到寄存器R2 ~ R9 STMIA R1,{R2-R9} ;存储寄存器R2-R9到目标地址上
使用LDM/STM进行现场保护,常用在子程序或异常处理中 STMFD SP!,{R0-R7,LR} ;寄存器入栈 .....
BL DELAY ;调用DELAY子程序 .....
LDMFD SP!,{R0-R7,PC} ;恢复寄存器,并返回
SWP是寄存器和存储器交换指令,可使用SWP实现信号量操作 12C_SEM EQU 0x40003000 ;EQU定义一个常量 12C_SEM_WAIT ;标签 MOV R1,#0
LDR R0,=12C_SEM
SWP R1,R1,[R0] ;取出信号量,并设置为0 CMP R1,#0 ;判断是否有信号 BEQ 12C_SEM_WAIT ;若没有信号,则等待
ARM数据处理指令包括
1、数据传送指令 2、算术逻辑运算指令 3、比较指令 4、乘法指令
ADC指令:带进位加法指令,将操作数2的数据与Rn的值相加,再加上CPSR中C条件标志位,结果保存到Rd中 使用ADC指令实现64位加法
ADDS R0,R0,R2 ; R0+R2 => R0,影响CPSR中的值 ADC R1,R1,R3 ;(R1、R0) = (R1、R0)+(R3、R2)
SBC指令:带借位减法指令,用寄存器Rn减去操作数2,再减去CPSR中的C条件标志位的非(即若C标志清零,则结果减去1),结果保存在Rd中 使用SBC实现64位减法 SUBS R0,R0,R2
SBC R1,R1,R3 ;使用SBC实现64位减法,(R1,R0) - (R3,R2)
AND指令:按位与操作
ANDS R0,R0,#0x01 ;取出最低位数据
ORR指令:按位或操作
ORR R0,R0,#0x0F ;将R0的低4位置1
EOR指令是进行异或操作,BIC指令是位清除指令(遇1清0)
TST:位测试指令
TST R0,#0x01 ; 判断R0的最低位是否是为0
TEQ:相等测试指令
TEQ R0,R1 ; 比较R0与R1是否相等,也可看作相减,相等则为0,Z=1
MUL指令:乘法指令
MUL R1,R2,R3 ; R1=R2*R3
MULS R0,R3,R7 ; R0=R3*R7,同时设置CPSR中的N位和Z位
MLA是乘加指令,将操作数1和操作数2相乘再加上第3个操作数,结果的低32位存入到Rd中
UMULL是64位无符号乘法指令
UMULL R0,R1,R5,R8 ; (R1、R0) = R5 * R8
BL指令:带链接的跳转指令,指令将下一条指令拷贝到R14(即LR)链接寄存器中,然后跳转到指定地址运行
BL指令用于子程序调用,例如:BL DELAY
BX指令:带状态切换的跳转指令,例如 BX R0 ;跳转到R0指定的地址,并根据R0的最低位来切换处理器的状态
MCR:ARM寄存器到协处理器寄存器的数据传送指令 MRC:协处理器寄存器到ARM寄存器的数据传送指令
MRC/MCR指令格式如下:
MRC/MCR {cond} coproc,opcode1,Rd,CRn,CRm{,opcode2} coproc是指令操作的协处理器名,标准名为pn,n为0-15 opcode1 协处理器的特定操作码
Rd MRC操作时,作为目标寄存器的协处理器寄存器,MCR操作时,作为ARM处理器的寄存器
CRn 存放第1个操作数的协处理器寄存器 CRm 存放第2个操作数的协处理器寄存器 opcode2 可选的协处理器特定操作码
MRC/MCR指令举例如下: mcr/mrc p15,0,r0,c1,c0,0
SWI指令:SWI指令用于产生中断,从而实现用户模式变换到管理模式,CPSR保存到管理模式的SPSR中,执行转移到SWI向量 SWI 0x123456 ;软中断,中断立即数 0x123456
在SWI异常中断处理程序中,取出SWI立即数的步骤为:首先确定引起软中断的SWI指令是ARM指令还是THUMB指令,这可通过对SPSR访问得到,然后要取得该SWI指令的地址,这可通过访问LR寄存器得到,接着读出指令,分解出立即数
程序代码如下:
T_bit EQU 0x20 ;0010 0000 SWI_Hander
STMFD SP!,{R0-R3,R12,LR} ;现场保护 MRS R0,SPSR ;读取SPSR STMFD SP!,{R0} ;保存SPSR
TST R0, #T_bit ;测试T标志位,0为ARM,1为THUMB LDRNEH R0,[LR,#-2] ;若是THUMB指令,读出产生中断的指令码(16位)
BICNE R0,R0,#0xFF00 ;取得THUMB指令的8位立即数
LDREQ R0,[LR,#-4] ;若是ARM指令,读取产生中断的指令码(32
位)
BICEQ R0,R0,#0xFF000000 ;取得ARM指令的24位立即数 BL C_SWI_Handler
LDMFD SP!,{R0-R3,R12,PC}^ ;SWI异常中断返回
MRS指令:读状态寄存器指令,在ARM处理器中,只有MRS指令可以从状态寄存器CPSR或SPSR读出到通用寄存器
MRS R1,CPSR ;将CPSR状态寄存器读取,保存到R1 MRS R2,SPSR ;将SPSR状态寄存器读取,保存到R2
MRS应用:
1、使能IRQ中断 ENABLE_IRQ MRS R0,CPSR
BIC R0,R0,#0x80 ;1000 0000 MSR CPSR,R0 MOV PC,LR
2、禁止IRQ中断 DISABLE_IRQ MRS R0,CPSR
ORR R0,R0,#0x80 MSR CPSR,R0 MOV PC,LR
MSR:写状态寄存器指令,在ARM处理器中,只有MSR指令可以直接设置状态寄存器CPSR或SPSR
================================================================================================================
ARM伪指令介绍
ARM伪指令不是ARM指令集中的指令,只是为了编程方便编译器定义了伪指令 ARM地址读取伪指令有四条,分别是 ADR 伪指令 ADRL 伪指令 LDR 伪指令 NOP 伪指令
作用的范围不一样,由小到大: ADR,ADRL,LDR
ADR、ADRL指令将基于PC相对偏移的地址读取到存储器中,例如 ADR R0 , DISP_TAB ; 加载转换表地址
LDR R1, [R0,R2] ;使用R2作为参数,进行查表 ..... DISP_TAB DCB
0xc0,0xf9,0xa4,0x99,0x92,0x82,0xf8,0x80
LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器,前加 = LDR R0,=0x123456 ;加载32位立即数0x123456 LDR R0,=DATA_BUF+60 ;加载DATA_BUF地址+60
NOP是空操作伪指令
宏是一段独立的程序代码,它是通过伪指令定义的,在程序中使用宏指令即可调用宏,当程序被汇编时,汇编程序将对每个调用进行展开,用宏定义取代源程序中的宏指令
符号定义伪指令
1、全局变量声明:GBLA、GBLL 和 GBLS 2、局部变量声明:LCLA、LCLL 和 LCLS 3、变量赋值:SETA、SETL、和 SETS
4、为一个通用寄存器列表定义名称:RLIST 5、为一个协处理器的寄存器定义名称:CN 6、为一个协处理器定义名称:CP
最后一个字符 A代表算术变量,初始值为0,L代表逻辑变量,初值为FALSE,S代表字符串,初值为空 伪指令应用举例如下:
MACRO ;声明一个宏
SENDDAT $dat ;宏的原型 $表示后面是变量 LCLA bitno ;声明一个局部算术变量 ...
bitno SETA 8 ;设置变量值为8 ...
MEND ;结束
RLIST指令格式: name RLIST {reglist},例如: LoReg RLIST {R0-R7} ;定义寄存器列表LoReg
CN指令的用法: