电工学习网

 找回密码
 立即注册

ARM指令集

2015-3-23 07:58| 编辑:电工学习网| 查看: 23031| 评论: 0



     关于“LDR和STR——字和无符号字节加载/存储指令编码”:

     关于“LDR和STR——字和无符号字节加载/存储指令”:LDR/STR指令寻址非常灵活,它由两部分组成,其中一部分为一个基址寄存器,可以为任一个通用寄存器;另一部分为一个地址偏移量。地址偏移量有以下3种格式:
     (1)立即数。立即数可以是一个无符号的数值。这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 如:LDR R1,[R0,#0x12]
     (2)寄存器。寄存器中的数值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 如:LDR R1,[R0,R2]
     (3)寄存器及移位常数。寄存器移位后的值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 如:LDR R1,[R0,R2,LSL #2]
     从寻址方式的地址计算方法分,加载/存储指令有以下4种格式:
     (1)零偏移。 如:LDR Rd,[Rn]
     (2)前索引偏移。 如:LDR Rd,[Rn,#0x04]!
     (3)程序相对偏移。 如:LDR Rd,labe1
     (4)后索引偏移。 如:LDR Rd,[Rn],#0x04
     注意:大多数情况下,必须保证字数据操作的地址是32位对齐的。
     关于“LDR和STR——半字和有符号字节加载/存储指令”:这类LDR/STR指令可加载有符号半字或字节,可加载/存储无符号半字。偏移量格式、寻址方式与加载/存储字和无符号字节指令相同。
     LDR{cond}SB Rd,<地址> ;将指定地址上的有符号字节读入Rd
     LDR{cond}SH Rd,<地址> ;将指定地址上的有符号半字读入Rd
     LDR{cond}H Rd,<地址> ;将指定地址上的半字数据读入Rd
     STR{cond}H Rd,<地址> ;将Rd中的半字数据存入指定地址
     注意:1.有符号位半字/字节加载是指用符号位加载扩展到32位,无符号半字加载是指用零扩展到32位;
     2.半字读写的指定地址必须为偶数,否则将产生不可靠的结果;

     下面介绍一下,LDR和STR指令应用示例:
     1.加载/存储字和无符号字节指令LDR R2,[R5] ;将R5指向地址的字数据存入R2STR R1,[R0,#0x04] ;将R1的数据存储到R0+0x04地址LDRB R3,[R2],#1 ;将R2指向地址的字节数据存入R3,R2=R2+1STRB R6,[R7] ;将R7指向地址的字节数据存入R6
     2.加载/存储半字和有符号字节指令LDRSB R1,[R0,R3] ;将R0+R3地址上的字节数据存入R1;高24位用符号扩展LDRH R6,[R2],#2 ;将R2指向地址的半字数据存入R6,高16位用0扩展;读出后,R2=R2+2STRH R1,[R0,#2]! ;将R1的半字数据保存到R0+2地址,只修改低2字节数据,R0=R0+2

     多寄存器加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDM为加载多个寄存器;STM为存储多个寄存器。允许一条指令传送16个寄存器的任何子集或所有寄存器。它们主要用于现场保护、数据复制、常数传递等。
     多寄存器加载/存储指令格式如下:
     (1)LDM{cond}<模式> Rn{!},reglist{^}
     (2)STM{cond}<模式> Rn{!},reglist{^}
     cond:指令执行的条件;
     模式:控制地址的增长方式,一共有8种模式;
     !:表示在操作结束后,将最后的地址写回Rn中;
     reglist :表示寄存器列表,可以包含多个寄存器,它们使用“,”隔开,如{R1,R2,R6-R9},寄存器由小到大排列;
     ^:加入该后缀后,进行数据传送且寄存器列表不包含PC时,加载/存储的寄存器是用户模式下的,而不是当前模式的寄存器。若在LDM指令且寄存器列表中包含有PC时使用,那么除了正常的多寄存器传送外,还将SPSR也拷贝到CPSR中,这可用于异常处理返回。
     注意:该后缀不允许在用户模式或系统模式下使用。
     关于“LDM和STM——多寄存器加载/存储指令编码”:

      多寄存器加载/存储指令的8种模式如下表所示,右边四种为堆栈操作、左边四种为数据传送操作。

      进行数据复制时,先设置好源数据指针和目标指针,然后使用块拷贝寻址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB进行读取和存储 。
     进行堆栈操作操作时,要先设置堆栈指针(SP),然后使用堆栈寻址指令STMFD/LDMFD 、STMED/LDMED、STMFA/LDMFA和STMEA/LDMEA实现堆栈操作。

     堆栈操作(详见“4.1 寻址方式堆栈寻址”)和数据块传送指令类似,也有4种模式,它们之间的关系如下表所示:

     两段代码的执行结果是一样的,但是使用堆栈指令的压栈和出栈操作编程很简单(只要前后一致即可),而使用数据块指令进行压栈和出栈操作则需要考虑空与满、加与减对应的问题。
     关于“ARM存储器访问指令——寄存器和存储器交换指令”:

     SWP指令用于将一个内存单元(该单元地址放在寄存器Rn中)的内容读取到一个寄存器Rd中,同时将另一个寄存器Rm的内容写入到该内存单元中。使用SWP可实现信号量操作。
     指令格式如下: SWP{cond}{B} Rd,Rm,[Rn]
     其中,B为可选后缀,若有B,则交换字节,否则交换32位字;Rd用于保存从存储器中读入的数据;Rm的数据用于存储到存储器中,若Rm与Rn相同,则为寄存器与存储器内容进行交换;Rn为要进行数据交换的存储器地址,Rn不能与Rd和Rm相同。
     SWP和SWPB——寄存器和存储器交换指令编码

     关于“ARM指令集——ARM数据处理指令”:数据处理指令大致可分为3类:
     (1)数据传送指令;(2)算术逻辑运算指令;(3)比较指令。
     数据处理指令只能对寄存器的内容进行操作,而不能对内存中的数据进行操作。所有ARM数据处理指令均可选择使用S后缀,并影响状态标志。
     下面讲讲“ARM数据处理指令——指令编码”:

     关于“ARM数据处理指令——数据传送”:
     关于“加法运算指令——ADD”,指令将operand2的值与Rn的值相加,结果保存到Rd寄存器。 指令格式如下: ADD{cond}{S} Rd,Rn,operand2
     应用示例:
     ADDS R1,R1,#1 ;R1=R1+1,并影响标志位
     ADD R1,R1,R2 ;R1=R1+R2
     关于“减法运算指令——SUB”,指令用寄存器Rn减去operand2,结果保存到Rd中。指令格式如下:SUB{cond}{S} Rd,Rn,operand2
     应用示例:
     SUBS R0,R0,#1 ;R0=R0-1 ,并影响标志位
     SUBS R2,R1,R2 ;R2=R1-R2 ,并影响标志位
     关于“逆向减法运算指令——RSB”,指令将operand2的值减去Rn,结果保存到Rd中。指令格式如下: RSB{cond}{S} Rd,Rn,operand2
     应用示例:
     RSB R3,R1,#0xFF00 ;R3=0xFF00-R1
     RSBS R1,R2,R2,LSL #2 ;R1=(R2<<2)-R2=R2×3
     关于“带进位加法指令——ADC”,将operand2的值与Rn的值相加,再加上CPSR中的C条件标志位,结果保存到Rd寄存器。指令格式如下:
     ADC{cond}{S} Rd,Rn,operand2
     应用示例(使用ADC实现64位加法,结果存于R1、R0中):
     ADDS R0,R0,R2 ;R0等于低32位相加,并影响标志位
     ADC R1,R1,R3 ;R1等于高32位相加,并加上低位进位
     关于“带进位减法指令——SBC”,用寄存器Rn减去operand2,再减去CPSR中的C条件标志位的非(即若C标志清零,则结果减去1),结果保存到Rd中。指令格式如下:
     SBC{cond}{S} Rd,Rn,operand2
     应用示例(使用SBC实现64位减法,结果存于R1、R0中):
     SUBS R0,R0,R2 ; 低32位相减,并影响标志位
     SBC R1,R1,R3 ;高32位相减,并减去低位借位
     关于“带进位逆向减法指令——RSC”,指令用寄存器operand2减去Rn,再减去CPSR中的C条件标志位,结果保存到Rd中。指令格式如下:RSC{cond}{S} Rd,Rn,operand2
     应用示例(使用RSC指令实现求64位数值的负数 ):
     RSBS R2,R0,#0
     RSC R3,R1,#0
     关于“ARM数据处理指令——逻辑运算指令”
     逻辑与操作指令——AND,指令将operand2的值与寄存器Rn的值按位作逻辑“与”操作,结果保存到Rd中。指令格式如下: AND{cond}{S} Rd,Rn,operand2
     应用示例:
     ANDS R0,R0,#0x01 ;R0=R0&0x01,取出最低位数据
     AND R2,R1,R3 ;R2=R1&R3
     逻辑或操作指令——ORR指令将operand2的值与寄存器Rn的值按位作逻辑“或”操作,结果保存到Rd中。指令格式如下:ORR{cond}{S} Rd,Rn, operand2
     应用示例:
     ORR R0,R0,#0x0F ;将R0的低4位置1
     MOV R1,R2,LSR #24 ;使用ORR指令将R2的高8位
     ORR R3,R1,R3,LSL #8 ;数据移入到R3低8位中
     逻辑异或操作指令——EOR指令将operand2的值与寄存器Rn的值按位作逻辑“异或”操作,结果保存到Rd中。指令格式如下:EOR{cond}{S} Rd,Rn, operand2
     应用示例:
     EOR R1,R1,#0x0F ;将R1的低4位取反
     EOR R2,R1,R0 ;R2=R1^R0
     EORS R0,R5,#0x01 ; 将R5和0x01进行逻辑异或,;结果保存到R0,并影响标志位
     位清除指令——BIC,指令将寄存器Rn的值与operand2的值的反码按位作逻辑“与”操作,结果保存到Rd中。指令格式如下:BIC{cond}{S} Rd,Rn, operand2
     应用示例:
     BIC R1,R1,#0x0F ;将R1的低4位清零,其它位不变
     BIC R1,R2,R3 ;将R3的反码和R2相逻辑“与”,
     ;结果保存到R1中
     ARM数据处理指令——比较指令
     比较指令——CMP指令将寄存器Rn的值减去operand2的值,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下:CMP{cond}   Rn, operand2
     应用示例:
     CMP R1,#10 ; R1与10比较,设置相关标志位
     CMP R1,R2 ; R1与R2比较,设置相关标志位
     比较指令——CMP指令将寄存器Rn的值减去operand2的值,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下:CMP{cond}Rn, operand2
     注意:CMP指令与SUBS指令的区别在于CMP指令不保存运算结果。在进行两个数据的大小判断时,常用CMP指令及相应的条件码来操作。
     负数比较指令——CMN,指令使用寄存器Rn的值加上operand2的值,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下: CMN{cond} Rn, operand2
     应用示例:
     CMN R0,#1 ; R0+1,判断R0是否为1的补码
     如果是,则设置Z标志位
     注意:CMN指令与ADDS指令的区别在于CMN指令不保存运算结果。CMN指令可用于负数比较,比如CMN R0,#1指令则表示R0与-1比较,若R0为-1(即1的补码),则Z置位;否则Z复位。
     位测试指令——TST,指令将寄存器Rn的值与operand2的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令 格式如下:TST{cond} Rn, operand2
     应用示例:
     TST R0,#0x01 ; 判断R0的最低位是否为0
     TST R1,#0x0F ; 判断R1的低4位是否为0
     注意:TST指令与ANDS指令的区别在于TST指令不保存运算结果。TST指令通常与EQ、NE条件码配合使用,当所有测试位均为0时,EQ有效,而只要有一个测试位不为0,则NE有效。
     相等测试指令——TEQ指令将寄存器Rn的值与operand2的值按位作逻辑“异或”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下:TEQ{cond} Rn, operand2
     应用示例:
     TEQ R0,R1 ; 比较R0与R1是否相等 (不影响V位和C位)
     注意:TEQ指令与EORS指令的区别在于TEQ指令不保存运算结果。使用TEQ进行相等测试时,常与EQ、NE条件码配合使用。当两个数据相等时,EQ有效;否则NE有效。
     ARM指令集——乘法指令,ARM7TDMI具有三种乘法指令,分别为:(1)32×32位乘法指令;(2)32× 32位乘加指令;(3)32× 32位结果为64位的乘/乘加指令。
     乘法指令编码:
     ARM指令——乘法指令
     32位乘法指令——MUL指令将Rm和Rs中的值相乘,结果的低32位保存到Rd中。指令格式如下:MUL{cond}{S} Rd,Rm,Rs
     应用示例:
     MUL R1,R2,R3 ;R1=R2×R3
     MULS R0,R3,R7 ;R0=R3×R7,同时影响CPSR中的N位和Z位
     32位乘加指令——MLA指令将Rm和Rs中的值相乘,再将乘积加上第3个操作数,结果的低32位保存到Rd中。指令格式如下: MLA{cond}{S} Rd,Rm,Rs,Rn


看过《ARM指令集》的人还看了以下文章:

发表评论

最新评论

  • 嵌入式开发到底是做什么的?
  • FPGA芯片结构
  • FPGA工作原理
  • 嵌入式学习方法与心得
  • 嵌入式软件工程师必须要掌握哪些知识
  • 嵌入式系统开发的可靠性设计

电工学习网 ( )

GMT+8, 2021-12-6 20:44

Powered by © 2011-2021 www.shop-samurai.com 版权所有 免责声明 不良信息举报

技术驱动未来! 电工学习网—专业电工基础知识电工技术学习网站。

栏目导航: 工控家园 | 三菱plc | 西门子plc | 欧姆龙plc | plc视频教程