ARM汇编语言


ARM的条件码域
大部分ARM指令都可以条件执行,也就是根据CPSR中的条件标志位决定是否执行该指令。当条件满足时执行,当条件不满足时该指令被当做一条NOP指令。


(一)跳转指令
B        跳转指令
BL      保存返回地址的跳转指令
BX      带状态切换的跳转指令
BLX    保存返回地址和状态切换的跳转指令

B、BL和BLX(1)后面跟地址标号。BLX(1)为无条件执行指令
BX和BLX(2)后面跟寄存器

例:B  Lable
         BX  R0


(二)数据处理指令
数据处理指令又分为三类:数据传送指令,如MOV;  算数逻辑运算指令,如ADD,SUB,AND等;  比较指令,如TST等
比较指令不保存运算结果,只更新CPSR中相应的条件标志位
ARM汇编语言_第1张图片
默认情况下,数据处理指令不影响条件标志位,只有比较指令能够影响CPSR中的条件标志位。但可以通过添加S来影响条件标志位。如ADDS。

数据传送指令

 

MOV

MOV  R1,#0x6    ;R1=0x6

MOV  R0,R1       ;R0=R1

MOV  R3,R1,LSL #2   ;R3=R1<<2

MOV  R3,R1,LSL R2   ;R3=R1<<R2

数据传送指令

MVN

MVN  R1,#0x6     ;R1=~0x6

MVN  R0,R1       ;R0=~R1

MVN  R3,R1,LSL #2   ;R3=~(R1<<2)

MVN  R3,R1,LSL R2   ;R3=~(R1<<R2)

数据求反传送指令

算术指令

 

ADD

ADD  R1,R1,#0x6   ;R1=R1 + 0x6

ADD  R1R1R2     ;R1=R1 + R2

ADD  R3,R1,R2,LSL #2   ;R3=R1 + R2<<2

ADD  R3,R1,R2,LSL R6   ;R3=R1 + R2<<R6

加法指令

ADC

ADC  R1,R1,#0x6   ;R1=R1 + 0x6 + C

ADC  R1,R1,R2     ;R1=R1 + R2 + C

ADC  R3,R1,R2,LSL #2   ;R3=R1 + R2<<2 + C

ADC  R3,R1,R2,LSL R6   ;R3=R1 + R2<<R6 + C

带进位加法指令

注:因为是带进位的,所以还要加上CPSR中的C条件标志位的值

SUB

SUB  R1,R1,#0x6   ;R1=R1 - 0x6

SUB  R1,R1,R2     ;R1=R1 - R2

SUB  R3,R1,R2,LSL #2   ;R3=R1 - R2<<2

SUB  R3,R1,R2,LSL R6   ;R3=R1 - R2<<R6

减法指令

SBC

SBC  R1,R1,#0x6   ;R1=R1 - 0x6 - !C

SBC  R1,R1,R2     ;R1=R1 - R2 - !C

SBC  R3,R1,R2,LSL #2   ;R3=R1 - R2<<2 - !C

SBC  R3,R1,R2,LSL R6   ;R3=R1 - R2<<R6 - !C

带借位的减法指令

注:因为是带借位的,所以还要再减去CPSR中的C条件标志位的反码

RSB

RSB  R1,R1,#0x6   ;R1=0x6 - R1

RSB  R1,R1,R2    ;R1=R2 - R1

RSB  R3,R1,R2,LSL #2   ;R3=R2<<2 – R1

RSB  R3,R1,R2,LSL R6   ;R3=R2<<R6 – R1

逆向减法指令

RSC

RSC  R1,R1,#0x6   ;R1=0x6 – R1 - !C

RSC  R1,R1,R2     ;R1=R2 - R1 - !C

RSC  R3,R1,R2,LSL #2   ;R3=R2<<2 - R1 - !C

RSC  R3,R1,R2,LSL R6   ;R3=R2<<R6 - R1 - !C

带借位的逆向减法指令

注:因为是带借位的,所以还要再减去CPSR中的C条件标志位的反码

逻辑指令

 

AND

AND  R1,R1,#0x6   ;R1=R1 & 0x6

AND  R1,R1,R2     ;R1=R1 & R2

AND  R3,R1,R2,LSL #2   ;R3=R1 & (R2<<2)

AND  R3,R1,R2,LSL R6   ;R3=R1 & (R2<<R6)

逻辑与指令

ORR

ORR  R1,R1,#0x6   ;R1=R1 || 0x6

ORR  R1,R1,R2     ;R1=R1 || R2

ORR  R3,R1,R2,LSL #2   ;R3=R1 || (R2<<2)

ORR  R3,R1,R2,LSL R6   ;R3=R1 || (R2<<R6)

逻辑或

EOR

EOR  R1,R1,#0x6   ;R1=R1 ^ 0x6

EOR  R1,R1,R2    ;R1=R1 ^ R2

EOR  R3,R1,R2,LSL #2   ;R3=R1 ^ (R2<<2)

EOR  R3,R1,R2,LSL R6   ;R3=R1 ^ (R2<<R6)

逻辑异或指令

BIC

BIC  R1,R1,#0xF    ;将R1的低4位清零

BIC  R1,R1,R2      ;将R2的反码与R1逻辑与,结果保存到R1

BIC  R3,R1,R2,LSL #2 

BIC  R3,R1,R2,LSL R6   

位清除指令

注:将第一个源操作数的位清零,清零的位是最后一个操作数中所有为1的位

比较指令

 

CMP

CMP  R1,#10    ;R1与10比较,设置相关标志位

CMP  R1,R2     ;R1与R2比较,设置相关标志位

CMP  R1,R2,LSL #6   ; R2左移6位后与R1比较,设置相关标志位

CMP  R1,R2,LSL R3   ; R2左移R3位后与R1比较,设置相关标志位

比较指令

CMP{cond} Rn,operand2

注:指令使用寄存器Rn的值减去operand2的值,根据操作的结果理新CPSR

中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行

在进行两个数据大小判

断时,常用CMP指令及相应的条件码来操作

CMN

CMN  R1,#10    ;R1与10比较,设置相关标志位

CMN  R1,R2     ;R1与R2比较,设置相关标志位

CMN  R1,R2,LSL #6   ; R2左移6位后与R1比较,设置相关标志位

CMN  R1,R2,LSL R3   ; R2左移R3位后与R1比较,设置相关标志位

比较指令

CMN{cond} Rn,operand2

注:指令使用寄存器Rn的值加上operand2的值,根据操作的结果理新CPSR

中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行

TST

TST  R1,#0x0F      ;判断R1的低4位是否为0

TST  R1,R2     

TST  R1,R2,LSL #6 

TST  R1,R2,LSL R3

位测试指令

指令将寄存器Rn的值与operand2的值按位作逻辑与操作

当所有测试位均为0时,EQ有效,而只要有一个测试为不为0,则NE有

效.

TEQ

TEQ  R1,#0x0F      ;判断R1的低4位是否为0

TEQ  R1,R2     

TEQ  R1,R2,LSL #6 

TEQ  R1,R2,LSL R3

相等测试指令

指令寄存器Rn的值与operand2的值按位作逻辑异或操作,根据操作

的结果理新CPSR中相应条件标志位

常与EQ,NE条件码配合使用,当两个数据相等时,EQ有效,否则NE有效

乘法指令

 

MUL

MUL  R1,R2,R3    ;R1=R2×R3

32位乘法指令

UMULL

UMULL  R0,R1,R5,R8  ;(R1、R0)=R5×R8 

64位无符号乘法指令

相乘后,高32位在R1中,低32位在R0中

SMULL

SMULL R2,R3,R7,R6  ;(R3,R2)=R7×R6

64位有符号乘法指令

MLA

MLA  R1,R2,R3,R0  ;R1=R2×R3+R0

32位乘加指令.

指令将Rm和Rs中的值相乘,再将乘积加上第3个操作数,结果的低

UMLAL

UMLAL  R0,R1,R5,R8  ;(R1,R0)=R5×R8+(R1,R0)

64 位无符号乘加指令.

UMLAL{cond}{S} RdLo,RdHi,Rm,Rs

指令将Rm 和Rs 中的值作无符号数相乘,64 位乘积与

RdHi,RdLo相加,结果的低32位保存到RdLo中,而高32位保存到RdHi中

SMLAL

SMLAL R2,R3,R7,R6 ;(R3,R2)=R7×R6+(R3,R2)

64 位有符号乘加指令

杂类算数指令

CLZ
CLZ  R1,R2          ;R1中存放R2中操作数最高端0的个数
前导0个数计数指令
    

 

 (三)Load/Store指令

Load指令

 

LDR

LDR R1,[R0,#0x12]  ;将R0+0x12地址处的数据读出,保存到R1中(R0的值不变)

LDR R1,[R0,R2]    ;将R0+R2地址的数据计读出,保存到R1中(R0的值不变)

LDR R1,[R0,-R2,LSL #2] ;将R0-R2*4地址处的数据计读出,保存到R1中(R0,R2的值不变)

LDR R1,[R0,#0x12]! ;将R0+0x12地址处的数据读出,保存到R1中(R0= R0+0x12)

LDR R1,[R0,R2]!   ;将R0+R2地址的数据计读出,保存到R1中(R0= R0+R2)

LDR R1,[R0,-R2,LSL #2]!;将R0-R2*4地址处的数据计读出,保存到R1中(R0= R0-R2*4)

LDR R1,[R0],#0x12  ;将R0地址处的数据读出,保存到R1中(R0= R0+0x12)

LDR R1,[R0],R2     ;将R0+R2地址的数据计读出,保存到R1中(R0= R0+R2)

LDR R1,[R0],R2,LSL #0x12 ;将R0地址处的数据计读出,保存到R1中(R0= R0-R2*4)

LDR  R1,Lable      ;将Lable标号地址里的值保存到R1中

字数据读取指令

LDRB

与上述指令相同,只不过是针对一个字节大小的加载,目标寄存器的最低字节有效,高24位清零

字节数据读取指令

LDRH

与上述指令相同,只不过是针对半字大小的加载,目标寄存器的最低16位有效,高16位清零

半字节数据读取指令

LDRSB

与上述指令相同,只不过是针对一个字节大小的加载,且是有符号的,目标寄存器的最低字节有效,高24位设置成该字节数据的符号位的值

有符号的字节读取指令

LDRSH

与上述指令相同,只不过是针对半字大小的加载,且是有符号的,目标寄存器的低16位有效,高16位设置成该字节数据的符号位的值

有符号的半字数据读取指令

LDRT

T为可选后缀,若指令有T,那么即使处理器是在特权模式下,存储系统也将访问看成是处理器是在用户模式下.T在用户模式下无效,不能与前索引偏移一起使用T

前索引: LDR Rd,[Rn,#0x06]!

LDR Rd,[Rn,#-0x06]

用户模式的字数据读取指令

LDRBT

T为可选后缀,若指令有T,那么即使处理器是在特权模式下,存储系统也将访问看成是处理器是在用户模式下.T在用户模式下无效,不能与前索引偏移一起使用T

前索引: LDR Rd,[Rn,#0x06]!

LDR Rd,[Rn,#-0x06]

用户模式的字节数据读取指令

Store指令

 

STR

STR R1,[R0,#0x12]  ;将R1中的数据存储到R0+0x12地址中,(R0的值不变)

STR R1,[R0,R2]     ;将R1中的数据存储到R0+R2地址中,(R0的值不变)

STR R1,[R0,-R2,LSL #2]  ;将R1中的数据存储到R0-R2*4地址中,(R0,R2的值不变)

STR R1,[R0,#0x12]! ;将R1中的数据存储到R0+0x12地址中, (R0= R0+0x12)

STR R1,[R0,R2]!    ;将R1中的数据存储到R0+R2地址中, (R0= R0+R2)

STR R1,[R0,-R2,LSL #2]!    ;将R1中的数据存储到R0-R2*4地址中,(R0= R0-R2*4)

STR R1,[R0],#0x12   ;将R1中的数据存储到R0地址中, (R0= R0+0x12)

STR R1,[R0],R2      ;将R1中的数据存储到R0地址中, (R0= R0+R2)

STR R1,[R0],R2,LSL #0x12 ;将R1中的数据存储到R0地址中, (R0= R0-R2*4)

字数据存储指令

STRB

与上述指令相同,只不过是针对一个字节大小的存储,该字节数据为指令中存放源操作数的寄存器的低8位

字节数据存储指令

STRH

与上述指令相同,只不过是针对半字大小的存储,该半字数据为指令中存放源操作数的寄存器的低16位

字节数据存储指令

STRT

T为可选后缀,若指令有T,那么即使处理器是在特权模式下,存储系统也将访问看成是处理器是在用户模式下.T在用户模式下无效,不能与前索引偏移一起使用T

前索引: STR Rd,[Rn,#0x06]!

               STR Rd,[Rn,#-0x06]

用户模式的字数据存储指令

STRBT

T为可选后缀,若指令有T,那么即使处理器是在特权模式下,存储系统也将访问看成是处理器是在用户模式下.T在用户模式下无效,不能与前索引偏移一起使用T

前索引: STR Rd,[Rn,#0x06]!

STR Rd,[Rn,#-0x06]

用户模式的字节数据存储指令


  (四)批量Load/Store指令

地址变化方式有四种:
IA            事后递增方式
IB            事先递增方式
DA          事后递减方式
DB          事先递减方式

栈指针通常可以指向不同的位置。栈指针指向栈顶元素时称为FULL栈,栈指针指向于栈顶元素相邻的一个可用数据单元时称为EMPTY栈。
数据栈的增长方向也可以不同。当数据栈向内存地址减小的方向增长时,称为DESCENDING栈;当数据栈向内存地址增加的方向增长时,称为ASCENDING栈
综合这里两种特点,可以有以下四种数据栈:
FD       满堆栈递减
ED       空堆栈递减
FA       满堆栈递增
EA       空堆栈递增

LDM{cond}<模式>  Rn{!},{reglist}^ 
STM{cond}<模式>  Rn{!},{reglist}^
  • 其中,寄存器Rn为基址寄存器,装有传送数据的初始地址,Rn不允许为R15;
  • 后缀“!”表示最后的地址写回到Rn中,寄存器列表reglist可包含多于一个寄存器或寄存器范围,使用“,”分开,如{R1,R2,R6-R9},
  • “^”后缀不允许在用户模式和系统模式下使用,若在LDM指令用寄存器列表中包含有PC时使用,那么除了正常的多寄存器传送外,将SPSR拷贝到CPSR中,这可用于异常处理返回;使用“^”后缀进行数据传送且寄存器列表不包含PC时,加载/存储的是用户模式的寄存器,而不是当前模式的寄存器。(注:但是基址寄存器Rn使用的是当前模式下的寄存器)
  •   地址对准――这些指令忽略地址的位[1:0] 
指令中寄存器和内存单元的对应关系满足这样的规则,即编号低的寄存器对应于内存中低地址单元,编号高的寄存器对应于内存中高地址单元。

例:

LDMIA R0!,{R3-R9}  ;加载R0指向的地址上的多字数据,保存到R3~R9中,R0值更新

STMIA R1!,{R3-R9}  ;将R3~R9的数据存储到R1指向的地址上,R1值更新

STMFD SP!,{R0-R7,LR};现场保存,将R0~R7、LR入栈

LDMFD SP!,{R0-R7,PC}^;恢复现场,异常处理返回,同时将SPSR的值复制到CPSR

(五)状态寄存器访问指令
想要实现通用寄存器和状态寄存器的数据传输,必须使用状态寄存器访问指令。
  • 只有在特权模式下才能修改状态寄存器. 
  • 程序中不能通过MSR指令直接修改CPSR中的T控制位来实现ARM状态/Thumb状态的切换,必须使用BX指令完成处理器状态的切换(因为BX指令属转移指令,它会打断流水线状态,实现处理器状态切换).
  • MRS与MSR配合使用,实现CPSR或SPSR寄存器的读---修改---写操作

MRS

MRS  R1,CPSR

MRS  R2,SPSR 

将状态寄存器CPSR或SPSR的值传送到通用寄存器中

MSR

格式:

MSR{cond}  psr_fields,#immed_8r

MSR{cond}  psr_fields,Rm

fields 指定传送的区域.Fields可以是以下的一种或多种(字母必须为小写):

c      控制域屏蔽字节(psr[7…0])

x      扩展域屏蔽字节(psr[15…8])

s     状态域屏蔽字节(psr[23.…16])

f       标志域屏蔽字节(psr[31…24])

immed_8r        要传送到状态寄存器指定域的立即数,8位. 

Rm                    要传送到状态寄存器指定域的数据的源寄存器.

例:

MSR CPSR_c,#0xD3   ;CPSR[7…0]=0xD3,即切换到管理模式.

MSR CPSR_cxsf,R3   ;CPSR=R3

可以直接设置状态寄存器CPSR或SPSR

  

(六)信号量产生指令

指令格式:
SWP{cond}{B} Rd,Rm,[Rn]
Rd为数据从存储器加载 到的寄存器;
Rm的数据用于存储到存储器中,若Rm与Rn相同,则为寄存器与存储器内容 进行交换;
Rn为要进行数据交换的存储器地址,Rn不能与Rd和Rm相同

SWP

SWP  R1,R1,[R0]   ;将R1的内容与R0指向的存储单元的内容进行交换

交换指令

SWPB

SWP  R1,R2,,[R0]  ;将R0指向的存储单元内容读取一字节数据到R1中(高24位清零),并将R2的低8位写入到该内存单元(R0)中

字节交换指令




(七)异常中断指令

1、SWI(软中断指令)

指令格式如下; 
SWI{cond}     immed_24 
其中 immed_24 24位立即数,值为0~16777215之间的整数 

SWI指令举例如下: 
SWI 0  ;软中断,中断立即数为0
SWI 0x123456 ;软中断,中断立即数为0x123456

使用SWI指令时,通常使用以下两种方法进行传递参数,SWI异常中断处理程序就可以提供相关的服务,这两种方法均是用户软件协定。SWI 异常中断处理程序要通过读取引起软中断的SWI指令,以取得24位立即数. 

  • 指令24位的立即数指定了用户请求的服务类型,参数通过用寄存器传递 
MOV      R0,#34   ;设置了功能号为34
SWI       12    ;调用12号软中断
  • 指令中的24位立即数被忽略,用户请求的服务类型由寄存器R0的值决定,参数通过其它的通用寄存器传递. 
MOV      R0,#12   ;调用12号软中断
MOV      R1,#34   ;设置子功能号为34
SWI        0

在SWI异常中断处理程序中,取出SWI立即数的步骤为:
  1. 首先确定引起软中断的SWI指令是ARM指令还时Thumb指令,这可通过对SPSR访问得到:
  2. 然后要取得该SWI指令的地址,这可通过访问LR寄存器得到
  3. 接着读出指令,分解出立即数.

2、BKPT(断点中断指令)
BKPT指令用于产生软件断点中断。软件调试程序可以使用该中断。当系统使用硬件调试部件时可忽略该中断。

指令格式:
BKPT    <immediate>
其中,<immediate>为16位的立即数。该立即数被调试软件用来保存额外的断点信息。


(八)ARM协处理其操作指令

1、 CDP      协处理器数据操作指令

CDP{cond} coproc,opcodel,CRd,CRn,CRm{,opcode2} 
其中: 
coproc     指令操作的协处理器名.标准名为pn,n为0~15. 
opcode    l协处理器的特定操作码 
CRd         作为目标寄存器的协处理器寄存器. 
CRN         存放第1个操作数的协处理器寄存器. 
CRm         存放第2个操作数的协处理器寄存器. 
Opcode2 可选的协处理器特定操作码.  

例:
CDP   p5,2,c12,c10,c3,4          ;协处理器p5的初始化。其中,
                                                                    ;操作码1为2,操作码2为4
                                                                    ;目标寄存器为C12
                                                                    ;源操作数寄存器为C10和C3


2、 LDC     协处理器数据读取指令.LDC指令从某一连续的内存单元将数据读取到协处理器的寄存器中

LDC{cond}{L}  coproc,CRd,<地址> 
其中: 
L             可选后缀,指明是长整数传送. 
coproc   指令操作的协处理器名.标准名为pn,n 为0~15 
CRd       作为目标寄存的协处理器寄存器. 
<地址>  指定的内存地址 

例:
LDC   p5,c2,[R2,#4]            ;读取R2+4指向的内存单元的数据,传送到协处理器p5的c2寄存器中
LDC   p6,c2,[R1]                  ;读取是指向的内存单元的数据,传送到协处理器p6的c2寄存器


3、STC        协处理器数据写入指令.STC指令将协处理器的寄存器数据写入到某一连续的内存单元中

STC{cond}{L}  coproc,CRd,<地址> 
其中: 
L             可选后缀,指明是长整数传送. 
coproc   指令操作的协处理器名.标准名为pn,n为0~15 
CRd       作为目标寄存的协处理器寄存器. 
<地址>   指定的内存地址

例:
STC p5,c1,[R0]                          ;将 协处理器p5的c2寄存器中的值,存储到 R0指向的内存单元
STC p5,c1,[R0,#-0x04]              ;将 协处理器p5的c1寄存器中的值,存储到 R0+4指向的内存单元


注:MCR和MRC指令只能在处理器是系统模式时执行,在用户模式下执行将会触发未定义指令的异常中断。
4、MCR    ARM寄存器到协处理器寄存器的数据传送指令.MCR指令将ARM处理器的寄存器中的数据传送到协处理器的寄存器中

MCR{cond}     coproc,opcode1,Rd,CRn,CRm{,opcode2} 
其中:
coproc         指令操作的协处理器名.标准名为pn,n为0~15. 
cpcodel       协处理器的特定操作码. 
CRD             作为目标寄存器的协处理器寄存器. 
CRn              存放第1个操作数的协处理器寄存器 
CRm             存放第2个操作数的协处理器寄存器.  (用来区分同一个编号的不同物理寄存器,当不需要提供附加信息时,指定为C0)
Opcode2     可选的协处理器特定操作码.                 用来区分同一个编号的不同物理寄存器,当不需要提供附加信息时,指定为0

例:
MCR      p14,3,R7,c7,c11,6        ;指令从ARM寄存器中将数据传送到协处理器p14的寄存器中
                                                                      ;其中R7为ARM寄存器,存放源操作数;C7和C11为协处理器寄存器 为目标寄存器;
                                                                      ;操作码1为3,操作码2为6


5、MRC    协处理器寄存器到ARM寄存器到的数据传送指令.MRC指令将协处理器寄存器中的数据传送到ARM处理器的寄存器中.

MRC     {cond} coproc,opcode1,Rd,CRn,CRm{,opcode2} 
其中:
coproc         指令操作的协处理器名.标准名为pn,n,为0~15 
opcodel       协处理器的特定操作码. 
CRd             作为目标寄存器的协处理器寄存器. 
CRn             存放第1个操作数的协处理器寄存器. 
CRm            存放第2个操作数的协处理器寄存器. (用来区分同一个编号的不同物理寄存器,当不需要提供附加信息时,指定为C0)
opcode2     可选的协处理器特定操作码.                ( 用来区分同一个编号的不同物理寄存器,当不需要提供附加信息时,指定为0

例:
MRC        p15,2,R5,c0,c2,4         ;指令将协处理p15寄存器中的数据传送到ARM寄存器中
                                                                          ;其中,R5为ARM寄存器,是目标寄存器;C0和C2为协处理器寄存器,存放源操作数
                                                                          ;操作码1为2;操作码2为4







你可能感兴趣的:(ARM,arm处理器,微处理器)