常用ARM及汇编指令.docx

上传人:b****8 文档编号:10791915 上传时间:2023-02-22 格式:DOCX 页数:24 大小:29.79KB
下载 相关 举报
常用ARM及汇编指令.docx_第1页
第1页 / 共24页
常用ARM及汇编指令.docx_第2页
第2页 / 共24页
常用ARM及汇编指令.docx_第3页
第3页 / 共24页
常用ARM及汇编指令.docx_第4页
第4页 / 共24页
常用ARM及汇编指令.docx_第5页
第5页 / 共24页
点击查看更多>>
下载资源
资源描述

常用ARM及汇编指令.docx

《常用ARM及汇编指令.docx》由会员分享,可在线阅读,更多相关《常用ARM及汇编指令.docx(24页珍藏版)》请在冰豆网上搜索。

常用ARM及汇编指令.docx

常用ARM及汇编指令

用ARM指令及汇编包括2

指令集介绍4

ARM数据处理指令包括7

ARM伪指令介绍9

ARM汇编程序设计及一些格式要求说明13

 

用ARM指令及汇编包括

1、ARM处理器寻址方式

2、指令集介绍

3、伪指令

4、ARM汇编程序设计

5、C与汇编混合编程

ARM处理器寻址方式

1、寄存器寻址:

操作数的值在寄存器中,指令中的地址码字段指出的是寄存器编号,指令执行时直接取出寄存器值操作

MOV R1,R2       ;R2->R1

SUB R0,R1,R2   ;R1-R2-> R0

2、立即寻址:

立即寻址指令中的操作码字段后面的地址码部分就是操作数本身,也就是说,数据就包含在指令当中,取出指令就取出了可以立即使用的操作数

SUBSR0,R0,#1      ;R0-1->R0

MOV  R0,#0xff00   ;0xff00->R0

注:

立即数要以"#"为前缀,表示16进制数值时以"0x"表示

3、寄存器偏移寻址:

是ARM指令集特有的寻址方式,当第2操作数是寄存器偏移方式时,第2个寄存器操作数在与第1个操作数结合之前选择进行移位操作

MOV R0,R2,LSL#3      ;R2的值左移3位,结果存入R0,即R0=R2*8

ANDSR1,R1,R2,LSLR3  ;R2的值左移R3位,然后和R1相与操作,结果放入R1

寄存器偏移寻址可采用的移位操作如下

(1)、LSL(LogicalShiftLeft)逻辑左移,寄存器中字的低端空出补0

(2)、LSR(LogicalShiftRight)逻辑右移,寄存器中字的高端空出补0

(3)、ASR(ArthmeticShiftRight)算术右移,移位中保持符号位不变,即如果源操作数为正数,字高端空出补0,否则补1

(4)、ROR(RotateRight)循环右移,由字的低端移出的位填入高端空出的位

(5)、RRX(RotateRighteXtendedby1place),操作数右移一位,左侧空位由CPSR的C填充

4、寄存器间接寻址:

寄存器间接寻址指令中的地址码给出的是一个通用寄存器的编号,所需要的操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针

LDR R1,[R2]    ;将R2中的数值作为地址,取出此地址中的数据保存在R1中

SWPR1,R1,[R2];将R2中的数值作为地址,取出此地址中的数值与R1中的值交换

5、基址寻址:

将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址,基址寻址用于访问基址附近的存储单元,常用于查表,数组操作,功能部件寄存器访问等。

LDRR2,[R3,#0x0F]    ;将R3的数值加0x0F作为地址,取出此地址的数值保存在R2中

STRR1,[R0,#-2]     ;将R0中的数值减2作为地址,把R1中的内容保存到此地址位置

 

6、多寄存器寻址:

一次可以传送几个寄存器值,允许一条指令传送16个寄存器的任何子集或所有寄存器

LDMIAR1!

{R2-R7,R12} ;将R1所指向的地址的数据读出到R2-R7,R12,R1自动更新

STMIAR0!

{R3-R6,R10}  ;将R3-R6,R10中的数值保存到R0指向的地址,R0自动更新

7、堆栈寻址:

堆栈是特定顺序进行存取的存储区,堆栈寻址时隐含的使用一个专门的寄存器(堆栈指针),指向一块存储区域(堆栈),存储器堆栈可分为两种:

向上生长:

向高地址方向生长,称为递增堆栈

向下生长:

向低地址方向生长,称为递减堆栈

如此可结合出四中情况:

1、满递增:

堆栈通过增大存储器的地址向上增长,堆栈指针指向内含有效数据项的最高地址,指令如LDMFA,STMFA

2、空递增:

堆栈通过增大存储器的地址向上增长,堆栈指针指向堆栈上的第一个空位置,指令如LDMEA,STMEA

3、满递减:

堆栈通过减小存储器的地址向下增长,堆栈指针指向内含有效数据项的最低地址,指令如LDMFD,STMFD

4、空递减:

堆栈通过减小存储器的地址向下增长,堆栈指针指向堆栈下的第一个空位置,指令如LDMED,STMED

STMFDSP!

{R1-R7,LR} ;将R1-R7,LR入栈,满递减堆栈

LDMFDSP!

{R1-R7,LR} ;数据出栈,放入R1-R7,LR寄存器,满递减堆栈

8、块拷贝寻址:

多寄存器传送指令用于一块数据从存储器的某一位置拷贝到另一位置

STMIAR0!

{R1-R7}    ;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之后增加,方向为向上增长

STMIBR0!

{R1-R7}    ;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之前增加,方向为向上增长

SIMDAR0!

{R1-R7}    ;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之后增加,方向为向下增长

STMDBR0!

{R1-R7}    ;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之前增加,方向为向下增长

不论是向上还是向下递增,存储时高编号的寄存器放在高地址的内存,出来时,高地址的内容给编号高的寄存器

9、相对寻址:

是基址寻址的一种变通,由程序计数器PC提供基准地址,指令中的地址码字段作为偏移量,两者相加后得到的地址即为操作数的有效地址

BLROUTE1   ;调用到ROUTE1子程序

BEQLOOP    ;条件跳转到LOOP标号处

 

================================================================================================================

指令集介绍

指令格式:

{}{S},,{}

其中<>内的项是必须的,{}内的项是可选的

opcode  指令助记符,如LDR,STR等

cond    执行条件,如EQ,NE等

S       是否影响CPSR寄存器的值,书写时影响CPSR,否则不影响

Rd      目标寄存器

Rn      第一个操作数的寄存器

operand2第二个操作数

指令格式举例如下:

LDRR0,[R1]      ;读取R1地址上的存储器单元内容,执行条件AL(无条件执行)

BEQDATAEVEN     ;跳转指令,执行条件EQ,即相等跳转到DATAEVEN

ADDSR1,R1,#1    ;加法指令,R1+1=>R1影响CPSR寄存器,带有S

SUBNESR1,R1,#0xD;条件执行减法运算(NE),R1-0xD=>R1,影响CPSR寄存器,带有S

条件码表

条件码助记符

标志

含义

EQ

Z=1

相等

NE

Z=0

不相等

CS/HS

C=1

无符号数大于或等于

CC/LO

C=0

无符号数小于

MI

N=1

负数

PL

N=0

正数

VS

V=1

溢出

VC

V=0

没有溢出

HI

C=1,Z=0

无符号数大于

LS

C=0,Z=1

无符号数小于或等于

GE

N=V

带符号数大于或等于

LT

N!

=V

带符号数小于

GT

Z=0,N=V

带符号数大于

LE

Z=1,N!

=V

带符号数小于或等于

AL

 

任何无条件执行(指令默认条件)

条件码应用举例:

1、比较两个值大小,C代码如下:

if(a>b)a++;

elseb++;

写出相应的ARM指令

代码如下:

设R0为a,R1为b

CMPR0,R1             ;R0与R1比较

ADDHIR0,R0,#1    ;若R0>R1,则R0=R0+1

ADDLSR1,R1,#1    ;若R0<=R1,则R1=R1+1

2、若两个条件均成立,则将这两个数值相加

C代码为:

if((a!

=10)&&(b!

=20))a=a+b;

对应的ARM指令为:

CMPR0,#10    ;比较R0是否为10

CMPNER1,#20 ;若R0不为10,则比较R1是否为20

ADDNER0,R0,R1;若R0不为10且R1不为20,则执行R0=R0+R1

3、若两个条件有一个成立,则将这两个数值相加

C代码为:

 if((a!

=10)||(b!

=20))a=a+b;

对应的ARM指令为:

CMPR0,#10     

CMPEQR1,#20  

ADDNER0,R0,R1

ARM存储访问指令:

LDR、STR、LDM、STM、SWP

LDR/STR:

加载/存储字和无符号字节指令

从寻址方式的地址计算方法分,加载/存储指令有以下4种形式:

1,零偏移:

LDRRd,[Rn]

2,前索引偏移:

LDRRd,[Rn,#0x04]!

,LDRRd,[Rn,#-0x04]Rn不允许为R15

3,程序相对偏移:

LDRRd,label,label为程序标号,该形式不能使用后缀!

4,后索引偏移:

LDRRd,[Rn],#0x04,Rn不允许是R15

指令举例如下:

LDRR2,[R5]    ;加载R5指定地址上的数据(字),放入R2中

STRR1,[R0,#0x04]   ;将R1的数据存储到R0+0x04存储单元,R0的值不变(若有!

,则R0就要更新)

LDRBR3,[R2],#1   ;读取R2地址上的一字节数据并保存到R3中,R2=R2+1

STRHR1,[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:

空递增堆栈

批量加载/存储指令举例如下:

LDMIAR0!

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

STMIAR1!

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

STMFDSP!

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

LDMFDSP!

{R0-R7,PC}^;恢复现场,异常处理返回

使用LDM/STM进行数据复制

LDRR0,=SrcData   ;设置源数据地址,LDR此时作为伪指令加载地址要加=

LDRR1,=DstData   ;设置目标地址

LDMIAR0,{R2-R9}  ;加载8字数据到寄存器R2~R9

STMIAR1,{R2-R9}  ;存储寄存器R2-R9到目标地址上

使用LDM/STM进行现场保护,常用在子程序或异常处理中

STMFDSP!

{R0-R7,LR};寄存器入栈

.....

BLDELAY            ;调用DELAY子程序

.....

LDMFDSP!

{R0-R7,PC} ;恢复寄存器,并返回

SWP是寄存器和存储器交换指令,可使用SWP实现信号量操作

12C_SEMEQU0x40003000  ;EQU定义一个常量

12C_SEM_WAIT             ;标签

MOVR1,#0

LDRR0,=12C_SEM          

SWPR1,R1,[R0]           ;取出信号量,并设置为0

CMPR1,#0               ;判断是否有信号

BEQ12C_SEM_WAIT         ;若没有信号,则等待

ARM数据处理指令包括

1、数据传送指令

2、算术逻辑运算指令

3、比较指令

4、乘法指令

ADC指令:

带进位加法指令,将操作数2的数据与Rn的值相加,再加上CPSR中C条件标志位,结果保存到Rd中

使用ADC指令实现64位加法

ADDSR0,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位减法

SUBSR0,R0,R2

SBC R1,R1,R3 ;使用SBC实现64位减法,(R1,R0)-(R3,R2)

AND指令:

按位与操作

ANDSR0,R0,#0x01 ;取出最低位数据

ORR指令:

按位或操作

ORRR0,R0,#0x0F  ;将R0的低4位置1

EOR指令是进行异或操作,BIC指令是位清除指令(遇1清0)

TST:

位测试指令

TSTR0,#0x01    ;判断R0的最低位是否是为0

TEQ:

相等测试指令

TEQR0,R1     ;比较R0与R1是否相等,也可看作相减,相等则为0,Z=1

MUL指令:

乘法指令

MULR1,R2,R3  ; R1=R2*R3

MULSR0,R3,R7 ;R0=R3*R7,同时设置CPSR中的N位和Z位

MLA是乘加指令,将操作数1和操作数2相乘再加上第3个操作数,结果的低32位存入到Rd中

UMULL是64位无符号乘法指令

UMULLR0,R1,R5,R8  ;(R1、R0)=R5*R8

BL指令:

带链接的跳转指令,指令将下一条指令拷贝到R14(即LR)链接寄存器中,然后跳转到指定地址运行

BL指令用于子程序调用,例如:

BLDELAY

BX指令:

带状态切换的跳转指令,例如BXR0;跳转到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/mrcp15,0,r0,c1,c0,0

SWI指令:

SWI指令用于产生中断,从而实现用户模式变换到管理模式,CPSR保存到管理模式的SPSR中,执行转移到SWI向量

SWI0x123456 ;软中断,中断立即数0x123456

在SWI异常中断处理程序中,取出SWI立即数的步骤为:

首先确定引起软中断的SWI指令是ARM指令还是THUMB指令,这可通过对SPSR访问得到,然后要取得该SWI指令的地址,这可通过访问LR寄存器得到,接着读出指令,分解出立即数

程序代码如下:

T_bitEQU0x20               ;00100000

SWI_Hander

   STMFDSP!

{R0-R3,R12,LR} ;现场保护

   MRS R0,SPSR              ;读取SPSR

   STMFDSP!

{R0}            ;保存SPSR

   TSTR0,#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位)

   BICEQR0,R0,#0xFF000000  ;取得ARM指令的24位立即数

   BL C_SWI_Handler

   LDMFDSP!

{R0-R3,R12,PC}^ ;SWI异常中断返回

MRS指令:

读状态寄存器指令,在ARM处理器中,只有MRS指令可以从状态寄存器CPSR或SPSR读出到通用寄存器

MRSR1,CPSR    ;将CPSR状态寄存器读取,保存到R1

MRSR2,SPSR    ;将SPSR状态寄存器读取,保存到R2

MRS应用:

1、使能IRQ中断

ENABLE_IRQ

MRSR0,CPSR

BICR0,R0,#0x80      ;10000000

MSRCPSR,R0

MOVPC,LR

2、禁止IRQ中断

DISABLE_IRQ

MRSR0,CPSR

ORRR0,R0,#0x80

MSRCPSR,R0

MOVPC,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位的立即数或一个地址值到指定寄存器,前加=

LDRR0,=0x123456    ;加载32位立即数0x123456

LDRR0,=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       ;宏的原型$表示后面是变量

LCLAbitno          ;声明一个局部算术变量

...

bitnoSETA8       ;设置变量值为8

...

MEND               ;结束

RLIST指令格式:

nameRLIST{reglist},例如:

LoRegRLIST{R0-R7}  ;定义寄存器列表LoReg

CN指令的用法:

nameCNexpr,其中name是要定义的协处理器的寄存器名称,expr对应的协处理器的寄存器编号,数值范围0~15

MemSetCN1  ;将协处理器的寄存器1名称定义为MemSet

CP指令的用法,举例如下:

DivRunCP5  ;将协处理器5名称定义为DivRun

数据定义伪指令:

1、声明一个文字池:

LTORG

2、定义一个结构化的内存表的首地址:

MAP或^

3、定义结构化内存表中的一个数据域:

FIELD或#

4、分配一块内存空间,并用0初始化:

SPACE或%

5、分配一段字节内存单元,并用指定的数据初始化:

DCB

6、分配一段字的内存单元,并用指令的数据初始化:

DCD和DCDU

7、分配一段双字的内存单元,并用64位整数数据初始化:

DCQ和DCQU

8、分配一段半字的内存单元,并用指定的数据初始化:

DCW和DCWU

LTORG用于声明一个文子池,在使用LDR伪指令时,要在适当的地址加入LTORG声明文子池,这样就会把要加载的数据保存在文子池内,再用ARM的加载指令读出数据(若没有使用LTORG声明文子池,则汇编器会在程序末尾自动声明)

LTORG伪指令应用举例如下:

...

LDRR0,=0x12345678

ADDR1,R1,R0

MOVPC,LR

LTORG       ;声明文子池

DCD 0x333

DCD0x555

MAP用于定义一个结构化的内存表的首地址,^与MAP同义

MAP0x00,R9  ;定义内存表的首地址为R9

FIELD用于定义一个结构化内存表的数据域,#与FIELD同义

^_ISR_STARTADDRESS   ;^issynonymforMAP

HandleReset # 4     ;定义数据域HandleReset,长度为4字节

SPACE用于分配一块内存单元,并用0初始化,%与SPACE同义

伪指令应用举例如下:

AREADataRAM,DATA,READWROTE  ;声明一数据段,名为DataRAM

DataBufSPACE 1000           ;分配1000字节空间

DCB伪指令格式:

{label}DCBexpr{,expr}...

加{}的代表可有可无,DCD、DCW指令格式与DCB基本相同

ASSERT为断言错误伪指令,在汇编编译器对汇编程序的第二遍扫描中,若其中ASSERT条件不成立,ASSERT伪指令将报告该错误信息

ASSERTTop<>Temp   ;断言Top不等于Temp

ASSERT:

DEF:

ENDIAN_CHANGE     

汇编控制伪指令

1、条件汇编控制:

IF、ELSE和ENDIF

IF、ELSE和ENDIF伪指令能够根据条件把一段代码包括在汇编程序内或将其排除在程序之外

[与IF同义,|与ELSE同义,]与ENDIF同义

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 经济学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1