您好,欢迎访问三七文档
ARM指令集详解发布:2010-3-1911:42|作者:Saiu|来源:MCU嵌入式领域ARM可以用两套指令集:ARM指令集和Thumb指令集。本文介绍ARM指令集。在介绍ARM指令集之前,先介绍指令的格式。1指令格式(1)基本格式opcode{cond}{S}Rd,Rn{,opcode2}其中,内的项是必须的,{}内的项是可选的,如opcode是指令助记符,是必须的,而{cond}为指令执行条件,是可选的,如果不写则使用默认条件AL(无条件执行)。opcode指令助记符,如LDR,STR等cond执行条件,如EQ,NE等S是否影响CPSR寄存器的值,书写时影响CPSR,否则不影响Rd目标寄存器Rn第一个操作数的寄存器operand2第二个操作数指令格式举例如下:LDRR0,[R1];读取R1地址上的存储器单元内容,执行条件ALBEQDATAEVEN;跳转指令,执行条件EQ,即相等跳转到DATAEVENADDSR1,R1,#1;加法指令,R1+1=R1影响CPSR寄存器,带有SSUBNESR1,R1,#0xD;条件执行减法运算(NE),R1-0xD=R1,影响CPSR寄存器,带有S(2)第2个操作数在ARM指令中,灵活的使用第2个操作数能提高代码效率,第2个操作数的形式如下:#immed_8r常数表达式,该常数必须对应8位位图,即常数是由一个8位的常数循环移位偶数位得到。合法常量0x3FC、0、0xF0000000、200、0xF0000001等都是合法常量。非法常量0x1FE、511、0xFFFF、0x1010、0xF0000010等都是非法常量。常数表达式应用举例如下:MOVR0,#1;R0=1ANDR1,R2,#0x0F;R2与0x0F,结果保存在R1LDRR0,[R1],#-4;读取R1地址上的存储器单元内容,且R1=R1-4Rm寄存器方式,在寄存器方式下操作数即为寄存器的数值。寄存器方式应用举例:SUBR1,R1,R2;R1-R2=>R1MOVPC,R0;PC=R0,程序跳转到指定地址LDRR0,[R1],-R2;读取R1地址上的存储器单元内容并存入R0,且R1=R1-R2Rm,shift寄存器移位方式。将寄存器的移位结果作为操作数,但RM值保存不变,移位方法如下:ASR#n算术右移n位(1≤n≤32)LSL#n逻辑左移n位(1≤n≤31)LSR#n逻辑左移n位(1≤n≤32)ROR#n循环右移n位(1≤n≤31)RRX带扩展的循环右移1位typeRs其中,type为ASR,LSL,和ROR中的一种;Rs偏移量寄存器,低8位有效,若其值大于或等于32,则第2个操作数的结果为0(ASR、ROR例外)。寄存器偏移方式应用举例:ADDR1,R1,R1,LSL#3;R1=R1*9SUBR1,R1,R2,LSR#2;R1=R1-R2*4R15为处理器的程序计数器PC,一般不要对其进行操作,而且有些指令是不允许使用R15,如UMULL指令。(3)条件码使用指令条件码,可实现高效的逻辑操作,提高代码效率。表A-1给出条件码表。表A-1条件码表对于Thumb指令集,只有B指令具有条件码执行功能,此指令条件码同表A-?,但如果为无条件执行时,条件码助记符“AL”不能在指令中书写。条件码应用举例如下:比较两个值大小,并进行相应加1处理,C代码为:if(a>b)a++;elseb++;对应的ARM指令如下。其中R0为a,R1为b。CMPR0,R1;R0与R1比较ADDHIR0,R0,#1;若R0>R1,则R0=R0+1ADDLSR1,R1,#1;若R0<=R1,则R1=R1+1若两个条件均成立,则将这两个数值相加,C代码为:If((a!=10)&&(b!=20))a=a+b;对应的ARM指令如下,其中R0为a,R1为b。CMPR0,#10;比较R0是否为10CMPNER1,#20;若R0不为10,则比较R1是否20ADDNER0,R0,R1;若R0不为10且R1不为20,指令执行,R0=R0+R12ARM存储器访问指令ARM处理是加载/存储体系结构的典型的RISC处理器,对存储器的访问只能使用加载和存储指令实现。ARM的加载/存储指令是可以实现字、半字、无符/有符字节操作;批量加载/存储指令可实现一条指令加载/存储多个寄存器的内容,大大提高效率;SWP指令是一条寄存器和存储器内容交换的指令,可用于信号量操作等。ARM处理器是冯?诺依曼存储结构,程序空间、RAM空间及IO映射空间统一编址,除对对RAM操作以外,对外围IO、程序数据的访问均要通过加载/存储指令进行。表A-2给出ARM存储访问指令表。表A-2ARM存储访问指令表LDR和STR加载/存储字和无符号字节指令。使用单一数据传送指令(STR和LDR)来装载和存储单一字节或字的数据从/到内存。LDR指令用于从内存中读取数据放入寄存器中;STR指令用于将寄存器中的数据保存到内存。指令格式如下:LDR{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。LDR/STR指令寻址是非常灵活的,由两部分组成,一部分为一个基址寄存器,可以为任一个通用寄存器,另一部分为一个地址偏移量。地址偏移量有以下3种格式:(1)立即数。立即数可以是一个无符号数值,这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值。指令举例如下:LDRR1,[R0,#0x12];将R0+0x12地址处的数据读出,保存到R1中(R0的值不变)LDRR1,[R0,#-0x12];将R0-0x12地址处的数据读出,保存到R1中(R0的值不变)LDRR1,[R0];将R0地址处的数据读出,保存到R1中(零偏移)(2)寄存器。寄存器中的数值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。指令举例值。指令举例如下:LDRR1,[R0,R2];将R0+R2地址的数据计读出,保存到R1中(R0的值不变)LDRR1,[R0,-R2];将R0-R2地址处的数据计读出,保存到R1中(R0的值不变)(3)寄存器及移位常数。寄存器移位后的值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。指令举例如下:LDRR1,[R0,R2,LSL#2];将R0+R2*4地址处的数据读出,保存到R1中(R0,R2的值不变)LDRR1,[R0,-R2,LSL#2];将R0-R2*4地址处的数据计读出,保存到R1中(R0,R2的值不变)从寻址方式的地址计算方法分,加载/存储指令有以下4种形式:(1)零偏移。Rn的值作为传送数据的地址,即地址偏移量为0。指令举例如下:LDRRd,[Rn](2)前索引偏移。在数据传送之前,将偏移量加到Rn中,其结果作为传送数据的存储地址。若使用后缀“!”,则结果写回到Rn中,且Rn值不允许为R15。指令举例如下:LDRRd,[Rn,#0x04]!LDRRd,[Rn,#-0x04](3)程序相对偏移。程序相对偏移是索引形式的另一个版本。汇编器由PC寄存器计算偏移量,并将PC寄存器作为Rn生成前索引指令。不能使用后缀“!”。指令举例如下:LDRRd,label;label为程序标号,label必须是在当前指令的±4KB范围内(4)后索引偏移。Rn的值用做传送数据的存储地址。在数据传送后,将偏移量与Rn相加,结果写回到Rn中。Rn不允许是R15。指令举例如下:LDRRd,[Rn],#0x04地址对准--大多数情况下,必须保证用于32位传送的地址是32位对准的。加载/存储字和无符号字节指令举例如下:LDRR2,[R5];加载R5指定地址上的数据(字),放入R2中STRR1,[R0,#0x04];将R1的数据存储到R0+0x04存储单元,R0值不变LDRBR3,[R2],#1;读取R2地址上的一字节数据,并保存到R3中,R2=R3+1STRBR6,[R7];读R6的数据保存到R7指定的地址中,只存储一字节数据加载/存储半字和带符号字节。这类LDR/STR指令可能加载带符字节\加载带符号半字、加载/存储无符号半字。偏移量格式、寻址方式与加载/存储字和无符号字节指令相同。指令格式如下:LDR{cond}SBRd,地址;加载指定地址上的数据(带符号字节),放入Rd中LDR{cond}SHRd,地址;加载指定地址上的数据(带符号字节),放入Rd中LDR{cond}HRd,地址;加载半字数据,放入Rd中,即Rd昀低16位有效,高16位清零STR{cond}HRd,地址;存储半字数据,要存储的数据在Rd,昀低16位有效说明:带符号位半字/字节加载是指带符号位加载扩展到32位;无符号位半字加载是指零扩展到32位。地址对准--对半字传送的地址必须为偶数。非半字对准的半字加载将使Rd内容不可靠,非半字对准的半字存储将使指定地址的2字节存储内容不可靠。加载/存储半字和带符号字节指令举例如下:LDRSBR1[R0,R3];将R0+R3地址上的字节数据读出到R1,高24位用符号位扩展LDRSHR1,[R9];将R9地址上的半字数据读出到R1,高16位用符号位扩展LDRHR6,[R2],#2;将R2地址上的半字数据读出到R6,高16位用零扩展,R2=R2+1SHRHR1,[R0,#2]!;将R1的数据保存到R2+2地址中,只存储低2字节数据,R0=R0+2LDR/STR指令用于对内存变量的访问,内存缓冲区数据的访问、查表、外设的控制操作等等,若使用LDR指令加载数据到PC寄存器,则实现程序跳转功能,这样也就实现了程序散转。变量的访问NumCountEQU0x40003000;定义变量NumCount…LDRR0,=NumCount;使用LDR伪指令装载NumCount的地址到R0LDRR1,[R0];取出变量值ADDR1,R1,#1;NumCount=NumCount+1STRR1,[R0];保存变量值…GPIO设置GPIO-BASEEQU0Xe0028000;定义GPIO寄存器的基地址…LDRR0,=GPIO-BASELDRR1,=0x00FFFF00;装载32位立即数,即设置值STRR1,[R0,#0x0C];IODIR=0x00FFFF00,IODIR的地址为0xE002800CMOVR1,#0x00F00000STRR1,[R0,#0x04];IOSET=0x00F00000,IOSET的地址为0xE0028004…程序散转…MOVR2,R2,LSL#2;功能号乘上4,以便查表LDRPC,[PC,R2];查表取得对应功能子程序地址,并跳转NOPFUN-TABDCDFUN-SUB0DCDFUN-SUB1DCDFUN-SUB2…LDM和STM批量加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDM为加载多个寄存器,STM为存储多个寄存器。允许一条指令传送16个寄存器的任何子集或所有寄存器。指令格式如下:LDM{cond}模式Rn{!},reglist{^}STM{cond}模式Rn{!},reglist{^}LDM/STM的主要用途是现场保护、数据复制、参数传送等。其模式有8种,如下所列:(前面4种用于数据块的传输,后面4种是堆栈操作)。(1)IA:每次传送后地址加4(2)IB:每次传送前地址加4(3)DA:每次传送后地址减4(4)DB:每次传送前地址减4(5)FD:满递减堆栈(6)ED:空递增堆栈(7)FA:满递增堆栈(8)EA:空递增堆栈其中,寄存器Rn为基址寄存器,装有传送数据的初始地址,Rn不允许为R1
本文标题:ARM指令集详解
链接地址:https://www.777doc.com/doc-5270688 .html