ARM指令集

1. 常用ARM指令

1.1 跳转指令

  1. B:无条件跳转

  2. BL:带连接的跳转指令

  3. BX:带状态切换的无条件跳转

  4. BLX:带链接和状态切换的无条件跳转

例如:

B 0x1234          跳转到绝对地址0x1234的位置执行相应的代码
BL loc_234        跳转到目标loc_234地址去,这条指令一般用于子程序之间的调用
BX  R0            跳转到R0寄存器指定的地址,并且根据R0最低位来切换处理器状态
复制代码

1.2 比较指令

比较指令
eq:相等/z=1 ne:不相等/标志z=0
hi:无符号数大于/c=1,z=0 cs/hs:无符号数大于或等于/c=1
cc/lo:无符号数小于/c=0 ls:无符号数小于或等于/c=0,z=1
gt:有符号数大于/z=0,n=v ge:有符号数大于或等于/n=v
lt:有符号数小于/n!=v le:有符号数小于或等于/z=1,n!=v
mi:负数/n=1 pl:整数或0/n=0
vs:溢出/v=1 vc:没有溢出

2. 寄存器于储存器操作

2.1 寄存器的定义

存储器(主存,内存)

寄存器中放的数据:可以是字符串,可以是数,也可以是一个地址,可以放各种类型的数据。

例如:

地址(如0x00004000)与地址中存在的值
复制代码

2.2 寄存器常用指令

– LDR:从存储器中加载数据到寄存器 ← Load

例如:

LDR R8,(R9,#4)
复制代码

R8为待加载数据的寄存器,加载值为R9+0x4所指向的存储单元。

  1. 把后面的给前面的
  2. 把方括号里面的整体当做地址
LDR R8,[R9,#4]
复制代码

解释:将R9+4,取地址里面的值赋值给R8

LDR R8,R9,#4
复制代码

解释:将R9+4的值赋值给R8

– STR:将寄存器的数据存储到存储器 → Store

STR R8,[R9,#4] 
复制代码

将R8寄存器的数据存储到R9+0x4指向的存储单元。(将R8的值放到R9+4的地址)

– LDM:将存储器的数据加载到一个寄存器列表 →

LDM R0,{R1-R3}
复制代码

将R0指向的存储单元的数据依次加载到 R1,R2,R3寄存器。

  • STM:将一个寄存器列表的数据存储到指定的存储器 ←

  • PUSH: 将寄存器值推入堆栈(压栈)

  • POP:将堆栈值推出到寄存器(出栈)

  • SWP:将寄存器与存储器之间的数据进行交换

  • SWP:将寄存器与存储器之间的数据进行交换

SWP R1, R1 [R0]
复制代码

将R1寄存器与R0指向的存储单元的内容进行交换。

2.3 数据传送指令

  • SMOV:将立即数或寄存器的数据传送到目标寄存器
MOV R0, #8  
复制代码

即 R0=8

2.4 数据算术运算指令

ADD,SUB,MUL,DIV ←

有符号、无符号运算,带进位运算。

2.5 数据逻辑运算指令

  • 与:AND

  • 或:ORR

  • 异或:EOR

  • LSL(Logical Shift Left):逻辑左移←,寄存器中字的低端空出的位补0

  • LSR(Logical Shift Right):逻辑右移←,寄存器中字的高端空出的位补0

  • ASR(Arithmetic Shift Left):算数右移,位移过程中保持符号位不变,即如果源操作数为正数,则字的高端空出的位补0,否则补1

  • ROR(Rotate Right):循环右移,由字的低端移出的位填入字的高端空出的位

  • RRX(Rotate Right eXtended by lplace):带扩展的循环右移,操作数右移一位,高端空出的位用原C标志值填充

例如:

LSL R0,R1,#2
复制代码

即 R0=R1*4
在这里插入图片描述

2.6 比较指令

  • CMP:比较
CMP R0 #0 	
复制代码

R0寄存器中的值与0比较

标志位:如z位,这个都可以在动态调试时,寄存器窗口看到

2.7 其他指令

  • 协处理器指令:SWT (切换用户模式)
  • 伪指令:DCB

2.8 寄存器寻址方式

  • 立即寻址:立即寻址指令中的操作码字段后面的地址码部分就是操作数本身,也就是说,数据就包含在指令当中,取出指令也就取出了可以立即使用的操作数(立即数)。
MOV R0,R0,#1
R0-1 —> R0
 
MOV R0,#0xff00
0xff00 —> R0
复制代码
  • 寄存器寻址:操作数的值在寄存器中,指令中的地址码字段指出的是寄存器编号,指令执行时直接取出寄存器值操作。
MOV R0,R1
R1 —> R0
 
SUB R0,R1,R2
R1-R2 —> R0
复制代码
  • 寄存器偏移寻址:ARM指令集特有寻址方式,当第2操作数是寄存器偏移方式时,第2个寄存器操作数在与第1个操作数结合之前,选择进行位移操作。
MOV R0,R1,LSL #2
R2的值左移2位,结果放入R0,即R0=R2×4

ANDS R1,R1,R2,LSL,R3
R2的值左移R3位,然后和R1相与操作,结果放入R1
复制代码
  • 寄存器间接寻址:指令中的地址码给出的是一个通用寄存器编号,所需要的操作数保存在寄存器制定地址的储存单元中,即寄存器为操作数的地址指针。
LDR R0,[R1] 
将R1中的数值作为地址,取出此地址中的数据保存在R0中

SWP R1,R1,[R2]
将如中的数值作为地址,取出此地址中的数值与R1中的值交换
复制代码
  • 寄存器间接基址偏移寻址:是ARM指令集特有的寻址方式,当第2操作数是寄存器偏移方式时,第2个寄存器操作数在与第1个操作数结合之前,选择进行位移操作。
LDR R0,[R1,#-4]
将R1寄存器的值-0x4的值作为地址,取出地址中的值给R0

MOV R0,R2,LSL, #3
R2的值左移33位,结果放入R0,即R0=R2×8

ANDS R1,R1,R2,LSL, R3
R2的值左移R3位,然后和R1相于操作,结果放入R1
复制代码
  • 基址寻址:将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址,基址寻址用于访问基址附近的储存单元,常用于查表、数组操作、功能部件寄存器访问等。
LDR R2,[R3,#0x0F]
将R3中的数值加0x0F作为地址,取出此地址的数值保存在R2中

STR R1,[R0,#-2]
将R0中的数值减2作为地址,把R1中的内容保存到此地址位置
复制代码
  • 多寄存器寻址:一次可以传送几个寄存器值,允许一条指令传送16个寄存器的任何子集或所有寄存器。
LDMIA R1!,{R2-R7,R12}
将R1单元中的数据读出到R2-R7,R12,R1自动加1

STMIA R0!,{R3-R6,R10}
将R3-R6,R10中的数据保存到R0指向的地址,R0自动加1
复制代码
  • 堆栈寻址:特定顺序进行出去的存储区,操作顺序分为“后进先出”和“先进后出”,堆栈寻址时是隐含的,它使用一个专门的寄存器(堆栈指针)指向一块存储区域(堆栈),指针所指向的存储单元就是堆栈的栈顶。存储器堆栈可分为两种:
  • 向上生长:向高地址方向生长,称为递增堆栈
  • 向下生长:向低地址方向生长,称为递减堆栈

堆栈指针指向最后压入的堆栈的有效数据项,称为满堆栈;堆栈指针指向下一个要放入的空位置,称为空堆栈。这样就有4种类型的堆栈表示递增和递减的满堆栈和空堆栈的各种组合。

  • 满递增:堆栈通过增大存储器的地址向上增长,堆栈指针指向含有有效数据项的最高地址。指令如LDMFA,STMFA等。
  • 空递增:堆栈通过增大存储器的地址向上增长,堆栈指针指向堆栈上的第一个空位置。指令如LDMEA,STMEA等。
  • 满递减:堆栈通过减小存储器的地址向下增长,堆栈指针指向内含有效数据项的最低地址。指令如LDMFD,STMFD等。
  • 空递减:堆栈通过减小存储器的地址向下增长,堆栈指针指向堆栈下的第一个空位置。指令如LDMED,STMED等。
STMFD SP!,{R1-R7,LR}
将R1~R7,LR入栈。满递减堆栈。

LDMFD SP!,{R1-R7,LR}
数据出栈,放入R1~R7,LR寄存器。满递减堆栈。
复制代码

ARM指令与THUMB指令最明显的区别:连续地址相差4为ARM指令,相差2位THUMB指令。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享