第三章指令系统及程序设计.docx
- 文档编号:5863065
- 上传时间:2023-01-01
- 格式:DOCX
- 页数:38
- 大小:104.37KB
第三章指令系统及程序设计.docx
《第三章指令系统及程序设计.docx》由会员分享,可在线阅读,更多相关《第三章指令系统及程序设计.docx(38页珍藏版)》请在冰豆网上搜索。
第三章指令系统及程序设计
第三章指令系统及程序设计
教学目标
通过本章的学习,要理解Thumb-2的指令编码格式;掌握指令寻方式、Thumb-2指令格式,掌握存储器访问指令、数据处理指令、转移指令、杂项指令以及程序设计的方法;了解ARMCortex-M3中较新颖的指令用法。
本章介绍Thumb-2指令集,它是16位Thumb指令集的一个超集,同时支持16位和32位的指令,但不再支持32位ARM指令集,系统根据指令码来识别。
介绍程序设计包括汇编语和C语言。
3.1指令格式
指令的基本格式如下:
其中,<>号内的项是必需的,{}号内的项是可选的。
如
Opcode:
指令助读符,如MOV、LDR、STR等。
Cond:
指令执行条件码,如EQ、NE等,如表3.1所示。
S:
是否更新APSR寄存器的值。
P:
指令的编码类型,当P为.N时,该条指令编译为16位Thumb-2编码指令;当P为.W时,则该指令指定编译为32位Thumb-2编码指令,若未指定指令编码类型,则由编译器自动选择指令的类型,且根据指令存在的编码类型优先选择16位指令。
Rd:
目的寄存器。
Rn:
第1个操作数的寄存器。
Operand2:
第2个操作数
如程序清单L3.1所示。
程序清单L3.1汇编格式示例1
ADDSR1,R2,#1;R1=R2+1,其中S表示执行将更新APSR,指令编码为16位。
LDR.WR2,[R2,#0x20];将地址为R2+0x20单元的数据加载到R2中,此指令为32位编码。
在上述指令格式中,要特别注意第2个操作数(operand2),其形式有:
常数、立即数、寄存器方式、寄存器移位方式,应用非常灵活。
如程序清单L3.2所示。
程序清单L3.2汇编格式示例2
MOV.WR1,0x12341234;R1=0x12341234,常数表达式
MOVR1,0x1234;R1=0x1234,立即数
SUBR1,R1,R2;R1=R1-R2,寄存器方式
ADDR1,R1,R1,LSL#3;R1=R1+R1*8,寄存器移位方式
3.2条件码
Thumb-2指令集采用了条件码,在编写代中使用指令条件码可以实现高效的逻辑操作,提高代码的执行效率。
指令条件如表3.1所示。
在Cortex-M3中,对条件码的使用是有限制的,只有分支转移指令(B指令)才可以随意使用条件码,而对于其它指令,Cortex-M3引入了IF-THEN指令块,指令只有在这个块中才能加条件码,且必须加条件码。
表3.1指令条件码
条件码助记符
标志
含义
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
-
无条件执行
条件码操作如程序清单L3.3所示。
程序清单L3.3条件码操作示例
SUBR1,R0,#0x01
BEQlabel;当Z=1时,也即R0=0x01时,程序才转移到label中去。
3.3指令分类
3.3.1Thumb-2指令表
在Thumb-2指令中,有16位指令和32位指令。
参见表3.2-3.
表3.216位数据处理指令(26个)
指令助记符
功能描述
ADC
带进位加法
ADD
加法
AND
逻辑与
ASR
算术右移
BIC
位清0
CMN
负向比较(把一个数跟另一个数的二进制补码相比较)
CPY
把一个寄存器的值复制到另一个寄存器中
EOR
按位异或
LSL
逻辑左移
LSR
逻辑右移
MOV
寄存器加载数据,即能用于寄存器间的传输,也能用于加载立即数
MUL
乘法
MVN
加载一个数的NOT值(取到逻辑反的值)
NEG
取二进制补码
ORR
按位或
ROR
圆圈右移
SBC
带借位的减法
SUB
减法
TST
测试
REV
在一个32位寄存器中反转字节序
REVH
把一个32位寄存器分成两个16位数,在每个16位数中反转字节序
REVSH
把一个32位寄存器的低16位半字进行字节反转,然后带符号扩展到32位
SXTB
带符号扩展一个字节到32位
SXTH
带符号扩展一个半字到32位
UXTB
无符号扩展一个字节到32位
UXTH
无符号扩展一个半字到32位
表3.316位转移指令(7个)
指令助记符
功能描述
B
无条件转移
B
条件转移
BL
转移并连接。
用于调用一个子程序,返回地址被存储在LR中
BLX
使用立即数的BLX不要在Coretx-M3中使用
CBZ
比较,结果为0就转移,短转移
CBNZ
比较,结果非0就转移,短转移
IT
If-Then
表3.416位存储器数据传送指令(12)
指令助记符
功能描述
LDR
从存储器中加载字到一个寄存器中
LDRH
从存储器中加载半字到一个寄存器中
LDRB
从存储器中加载字节到一个寄存器中
LDRSH
从存储器中加载半字,再经过带符号扩展后存储在一个寄存器中
LDRSB
从存储器中加载字节,再经过带符号扩展后存储在一个寄存器中
STR
把一个寄存器按字存储到存储器中
STRH
把一个寄存器的低半字存储到存储器中
STRB
把一个寄存器的低字节存储到存储器中
LDMIA
加载多个字,并且在加载后自增基址寄存器
STMIA
存储多个字,并且在存储后自增基址寄存器
PUSH
将多个寄存器压入到栈中
POP
从栈中弹出多个值到寄存器中
表3.5其它16位指令(5)
指令助记符
功能描述
SVC
系统服务调用
BKPT
断点指令
NOP
无操作
CPSIE
使能:
PRIMASK(CPSIEi);FAULTMASK(CPSIEf)清0相应位
CPSID
禁止:
PRIMASK(CPSIDi);FAULTMASK(CPSIDf)置1相应位
表3.632位数据处理指令(47个)
指令助记符
功能描述
ADC
带进位加法
ADD
加法
ADDW
宽加法(可以中12位立即数)
AND
逻辑与
ASR
算术右移
BIC
位清零
BFC
位段清零
BFI
位段插入
CMN
负向比较(把一个数和另一个数的二进行补码比较,并更新标志位)
CMP
比较两个数并更新标志位
CLZ
计算前导零的数目
EOR
逻辑异或
LSL
逻辑左移
LSR
逻辑右移
MLA
乘加
MLS
乘减
MOVW
把16位立即数放到寄存器的低16位,高16位清0
MOV
加载16位立即数到寄存器
MOVT
把16位立却数放到寄存器的高16位,低16位不变
MVN
移一个数的补码
MUL
乘法
ORR
逻辑或
ORN
把源操作数按位取反后,再执行按位或
RBIT
位反转(把一个32位整数用二进行表达后,再旋转180度)
REV
对一个32位整数按字节反转
REVH/REV16
对一个32位整数的高低半字都执行字节反转
REVSH
对一个32位整数的低半字执行字节反转,再带符号扩展成32位数
ROR
圆圈右移
RRX
带进位位的逻辑右移一格
SFBX
从一个32位整数中提取任意长度和位置的位段,并带符号扩展成32位整数
SDIV
带符号除法
SMLAL
带符号长乘加
SMULL
带符号长乘法
SSAT
带符号的饱和运算
SBC
带借位的减法
SUB
减法
SUBW
宽减法,可以减12位立即数
SXTB
字节带符号扩展到32位数
TEQ
测试是否相等
TST
测试
UBFX
无符号位段提取
UDIV
无符号除法
UMLAL
无符号长乘加
UMULL
无符号长乘法
USAT
无符号饱和操作
UXTB
字节被无符号扩展到32位
UXTH
半字被无符号扩展到32位
表3.732位存储器数据传送指令(13)
指令助记符
功能描述
LDR
加载字到寄存器
LDRB
加载字节到寄存器
LDRH
加载半字到寄存器
LDRSH
加载半字到寄存器,再带符号扩展到32位
LDM
从一片连续的地址空间中加载若干个字,并选中相同数目的寄存器放进去
LDRD
从连续的地址空间加载双字(64位整数)到两个寄存器
STR
存储寄存器中的字
STRB
存储寄存器中的低字节
STRH
存储寄存器中的低半字
STM
存储若干寄存器中的字到一片连续的地址空间中,占用相同数目的字
STRD
存储两个寄存器组成的双字到连续的地址空间中
PUSH
把若干寄存器值压入堆栈中
POP
从堆栈中弹出若干寄存器的值
表3.832位转移指令(20)
指令助记符
功能描述
B
无条件转移
BL
转移并连接
TBB
以字节为单位的查表转移。
从一个字节数组中选一8位前向跳转地址并转移
TBH
以半字为单位的查表转移。
从一个半字数组中选一个16位前向跳转的地址并转移
LDREX
加载字到寄存器,并且在内核中标明一段地址进入了互斥访问状态
LDREXH
加载半字到寄存器,并且在内核中标明一段地址进入了互斥访问状态
LDREXB
加载字节到寄存器,并且在内核中标明一段地址进入了互斥访问状态
SRTEX
检查将要写入的地址是否进入了互斥访问状态,如果是则存储寄存器字
STREXH
检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器半字
STREXB
检查将要写入地址是否已进入了互斥访问状态,如果是则存储寄存器的字节
CLREX
在本地处理器上清除互斥访问状态的标记
MRS
加载特殊功能寄存器值到通用寄存器
MSR
存储通用寄存器的值到特殊功能寄存器
NOP
无操作
SEV
发送事件
WFE
休眠并且在发生事件时被唤醒
WFI
休眠并且在发生中断的时被唤醒
ISB
指令同步隔离(与流水线和MPU等有关)
DSB
数据同步隔离(与流水线、MPU和cacha等有关)
DMB
数据存储隔离(与流水线、MPU和cacha等有关)
3.3.2Thumb-2指令的使用
1.存储器访问指令
Cortex-M3处理器对存储器的访问只能通过加载和存储指令来实现。
(1)、LDR和STR——加载存储指令
LDR指令是用于从存储器读取数据放入寄存器中:
SRT指令是用于将寄存器中的数据保存到存储器。
LDR和STR指令寻址非常灵活,由两部分组成,一部分为一个基址寄存器,可以为任意一个通用寄存器;另一部分为一个地址偏移量。
地址偏移量可以有以下三种格式:
①立即数:
立即数可以是一个无符号的数值,这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值。
应用示例见程序清单L3.4所示。
程序清单L3.4立即数操作示例
LDRR1,[R0,#0x12];将R0+0x12地址处的数据读出,保存到R1中
LDR.WR1,[R0,#-0x12];将R0-0x12地址处的数据读出,保存到R1中
LDRR1,[R0];将R0地址处的数据读出,保存到R1中
②寄存器:
寄存器中的数值可以加到基址寄存器中,也可以从基址寄存器减去这个数值。
应用示例见程序清单L3.5所示。
程序清单L3.5寄存器数据操作示例
LDRSBR1,[R0,R3];将R0+R3地址上的字节数据读出,保存到R1,
;高24位用符号位扩展
LDR.WR1,[R0,-R2];将R0-R2地址处的数据读出,保存到R1中。
说明:
有符号位半字、字节加载是指用符号位加载扩展数据达到32位,而无符号位半字加载是指零扩展到32位。
③寄存器及移位常数:
寄存器移位后的值可以加开基地址寄存器,也可以从基地址寄存器中减去这个数值。
应用示例见程序清单L3.6所示。
程序清单L3.5寄存器及移位常数操作示例
LDR.WR1,[R0,R2,LSL#2];将R0+(R2<<2)地址处的数据读出,保存到R1。
LDR.WR1,[R0,-R2,LSL#2];将R0-(R2<<2)地址处的数据读出,保存到R1。
从寻址方式的地址计算方法分,加载和存储指令可以有以下4种形式:
④零偏移:
Rn的值作为传送数据的地址,即地址偏移量为0。
⑤前索引偏移:
在数据传送之前,将偏移量加到Rn中,基结果作为数据传送的存储地址。
若使用后缀“!
”,则结果回写到Rn中,且Rn的值不允许为R15。
应用示例见程序清单L3.7所示。
程序清单L3.7前索引偏移操作示例
LDR.WRd,[Rn,#0x04]!
;将Rn+0x04地址处的数据读出,保存到Rd,然后
;将Rn+0x04的值更新到Rn中。
⑥后索引偏移:
Rn的值用做传送数据的存储地址。
在数据传送后,将偏移量与Rn相加,结果写回Rn中,Rn不允许是R15。
应用示例见程序清单L3.8所示。
程序清单L3.8后索引偏移操作示例
LDR.WRd,[Rn],#0x04;将Rn地址处的数据读出,保存到Rd,然后将Rn+0x0
;的值更新到Rn中
⑦程序相对偏移:
程序相对偏移是前索引形式的另一个版本。
汇编器由PC寄存器计算偏移量,并将PC寄存器作为Rn生成前索引指令。
不能使用后缀“!
”。
应用示例见程序清单L3.9所示。
程序清单L3.9后索引偏移操作示例
LDR.WRd,label;将标号label的地址装载到Rd中。
说明:
label为程序标号,若LDR指令为32位编码时,则label必须是在当前指令的±4KB范围内,但若LDR为16位编码指令时,label就必须在当前指令的+1KB范围内。
(2)、LDM和STM——多寄存器加载存储指令
LDM、STM指令主要用途是批量数据传送。
多寄存器加载、存储指令可以实现在一组寄存器和一块连续的内存单元之间传输出数据。
LDM为加载多个寄存器;STM为存储多个寄存器。
允许一条指令传送R0-R12和LR(R14)寄存器的任何子集或所有的寄存器。
指令的格式如下:
LDM{cond}<模式>Rn{!
},{reglist}
STM{cond}<模式>Rn{!
},{reglist}
其中<模式>如下:
IA:
每次传送后地址加4;
DB:
每次传送前地址减4;
FD:
满递减堆栈;
EA:
空递增堆栈。
其中“!
”:
表示最后的地址写到Rn中。
应用示例见程序清单L3.10所示。
程序清单L3.10多寄存器加载与存储操作示例
LDMFDR0!
,{R3-R9};加载R0指向的地址的多字数据,存到R3-R9中,R0更新。
STMIAR1!
,{R3-R9};将R3-R9的数据存储到R1指向的地址,R1的值更新。
STMDBSP!
,{R4-R11,LR};现场保护,将R4-R11、LR入栈。
LDMIASP!
,{R4-R11,PC};恢复现场。
LDR/STM和PUSH/POP指令的区别:
●LDR/STM能对任意的地址空间进行操作,而PUSH/POP只能支持堆栈空间进行操作;
●LDR/STM的生长方式可以支持向上和向下两种方式,而PUSH/POP只能支持向下生长;
●当两对指令的操作数都为SP时,LDR/STM可以选择是否回写修改SP值,而对PUSH/POP指令会自动修改SP值。
2.数据处理指令
数据处理指令可分为:
数据传送指令、算术运算指令、位段处理指令、字节反转指令、带符号扩展指令、比较指令、乘除法和饱和运算指令。
1数据传送指令
使用MOV指令可以用于寄存器间的数据传输,也能用于加载立即数。
应用示例见程序清单L3.11所示。
程序清单L3.11数据处理指令操作示例
MOVWR1,#0x1234;R1=0x1234,此指令的立即数为16位。
MOVTR1,#0x5678;此指令的立即数为16位;两条指令执行后,R1=0x56781234
;相当于:
R1=(R1&0x0000FFFF)|0x56780000
说明:
可以利用MOVW和MOVT指令的配合来完成32位立即数所传输。
2算术逻辑运算指令
算术逻辑运算包括:
加法指令、减法指令和移位操作指令。
其中移位操作指令主要有:
LSL:
逻辑左移,寄存器字的低端空出的位补0。
LSR:
逻辑右移,寄存器中字的高端空出的位补0。
ASR:
算术右移,移位过程中保持符号位不变,即若源操作数为正数,则字的高端空出位补0,否则补1。
ROR:
循环右移,由字的低端移出的位填入字的高端空出的位。
RRX:
带扩展的循环右移,操作数右移一位,高端空出的位用原C标志位填充。
各移位操作示意图如图3.1所示。
图3.1移位操作示意图
应用示例见程序清单L3.12所示。
程序清单L3.12算术逻辑运算指令操作示例
ADDSR1,R2,#123;R1=R2+123,并根据结果更新APSR的标志
SUBWR1,#123;R1=R1-123,不影响APSR的标志
ORNR1,R2,#0x123;R1=(~0x123)|R2,不影响APSR的标志
ADDR1,R2,R3LSL#3;R1=R2+R3<<3,不影响APSR。
3位段处理指令
位段处理指令包括:
位段清零、位段插入以及位反转指令,其对位处理的能力,特别是I/O处理的效率较高。
BFC(位段清零指令),把32位整数中任意一段连续的二进制位清0,语法如下:
BFC.WRd,#lsb,#width
其中,lsb为位段的末尾,width则指定在lsb和它的左边(更高有效位),共有多少个位参与操作。
应用示例见程序清单L3.13所示。
程序清单L3.13位段处理指令BFC操作示例
LDRR0,=0x1111FFFF;加载立即数给R0
BFCR0,#4,#10;从第4位开始连续10清零
执行完后,R0=0x1111C00F。
BFI(位段插入指令),把某个寄存器按LSB对齐的数值,复制到另一个寄存器的某个位段中,其格式为:
BFI.WRd,Rn,#lsb,#width
应用示例见程序清单L3.14所示。
程序清单L3.14位段处理指令BFI操作示例
LDRR0,=0x12345678;加载立即数给R0
LDRR1,=0xDDCCBBAA;加载立即数给R1
BFI.WR1,R0,#8,#16;从R0的LSB开始16位数插入R1第8位开始
执行后,R1=0xDD5678AA
UBFX、SBFX都是位段提取指令,语法格式为:
UBFX.WRd,Rn,#lsb,#width
SBFX.WRd,Rn,#lsb,#width
UBFX从Rn中取出任一个位段,执行零扩展后放到Rd中。
应用示例见程序清单L3.15所示。
程序清单L3.15位段处理指令UBFX操作示例
LDRR0,=0x5678ABCD
UBFX.WR1,R0,#16,#16;从R0的第12位开始的16位宽数据提取出放入R1。
则R1=0x00005678。
类似的,SBFX也提取任意的位段,但是以带符号的方式进行扩展。
应用示例见程序清单L3.16所示。
程序清单L3.16位段处理指令SBFX操作示例
LDRR0,=0x5678ABCD
SBFX.WR1,R0,#8,#4
执行结果:
R1=0xFFFFFFFB。
RBIT位反转指令,它是按位反转的,相当于把32位整数的二进制表示法水平旋转180度。
其语法格式为:
RBIT.WRd,Rn
假设:
R1=0x12345678(二进制:
0001,0010,0011,0100,0101,0110,0111,1000),执行如下操作:
RBIT.WR0,R1
执行后,R0=0x1E6A2C48(二进制:
0001,1110,0110,1010,0010,1100,0100,1000).
这条指令单独使用时看不出什么作用,但是与其它指令组合使用时往往有特效,高级技巧常用到它。
在μC/OS-II操作系统中可以由该指完成查找处于就绪态的任务中,优先最高的任务。
4字节反转指令
字节反转指令专门服务于小端模式和大端模式的转换,最常用于网络应用程序中(网络字节序是大端,主机字节序常是小端)。
指令包含有:
REV、REVH、REV16、REVSH。
指令格式如下:
REVRd,Rm
REVHRd,Rm
REV16Rd,Rm
REVSHRd,Rm
其反转示意图如图3.2所示。
应用举例:
假设:
R0=0xAABBCCDD,在执行下列两条指令后:
REVR1,R0
REVHR2,R0
REV16R3,R0
则R1=0xDDCCBBAA,R2=0xAABBDDCC,R3=0xBBAADDCC。
图3.2反序操作
REVSH在REVH的基础上,还把转换后的半字做带符号扩展。
例如:
R0=AABBCCDD
REVSHR1,R0
则结果:
R1=0xFFFFCCDD。
5带符号扩展指令
带符号扩展指令主要有:
带符号扩展一个字节、带符号扩展一个半字以及相应的无符号扩展指令,其主要用于提取字中的某个字节信息或半字信息,是优化C语言的强制类型转换而设的,可把数据宽度转换成处理器喜欢的32位长度。
指令格式如下:
SXTBRd,Rn
SXTHRd,Rn
SXTBRd,Rn
UXTHRd,Rn
对于SXTB、SXTH数据带符号位扩展成32位整数;对于UXTB、UXTH高位清0。
假设R0=0xAABBCCDD,则:
SXTBR1,R0;R1=0x000000DD
SXTHR1,R0;R1=0xFFFFCCDD
UXTBR1,R0;R1=0x000000DD
UXTHR1,R0;R1=0x0000CCDD
6比较指令
比较指令包括:
比较指令和测试指令,该类指令自动更新APSR的标志位。
语法格式:
CMPRn,Rm;相当于SUBS
CMNRn,Rm;相当于ADDS
TSTRn,Rm;相当于ANDS
TEQRn,Rm;相当于EORS
应用示例见程序清单L3.17所示。
程序清单L3.17比较指令操作示例
CMPR0,R1;计算R0-R1的差,并且根据结果更新标志位
CMNR0,0x12;计算R0+0x12的和,并且更新标志位
TSTR0,R1;计算R0&R1,并根据结果更新标志位
TEQR0,0x12;计算R0^0x12,并根据结果更新标志位
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第三 指令系统 程序设计