Thumb指令集.docx

上传人:b****5 文档编号:6369250 上传时间:2023-01-05 格式:DOCX 页数:15 大小:46.49KB
下载 相关 举报
Thumb指令集.docx_第1页
第1页 / 共15页
Thumb指令集.docx_第2页
第2页 / 共15页
Thumb指令集.docx_第3页
第3页 / 共15页
Thumb指令集.docx_第4页
第4页 / 共15页
Thumb指令集.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

Thumb指令集.docx

《Thumb指令集.docx》由会员分享,可在线阅读,更多相关《Thumb指令集.docx(15页珍藏版)》请在冰豆网上搜索。

Thumb指令集.docx

Thumb指令集

Thumb指令集

Thumb指令集概述

为兼容数据总线宽度为16位的应用系统,ARM体系结构除了支持执行效率很高的32位ARM指令集以外,同时支持16位的Thumb指令集。

Thumb指令集是ARM指令集的一个子集,是针对代码密度问题而提出的,它具有16位的代码宽度。

与等价的32位代码相比较,Thumb指令集在保留32位代码优势的同时,大大的节省了系统的存储空间。

Thumb不是一个完整的体系结构,不能指望处理器只执行Thumb指令集而不支持ARM指令集。

当处理器在执行ARM程序段时,称ARM处理器处于ARM工作状态,当处理器在执行Thumb程序段时,称ARM处理器处于Thumb工作状态。

Thumb指令集并没有改变ARM体系底层的编程模型,只是在该模型上增加了一些限制条件,只要遵循一定的调用规则,Thumb子程序和ARM子程序就可以互相调用。

与ARM指令集相比较,Thumb指令集中的数据处理指令的操作数仍然是32位,指令地址也为32位,但Thumb指令集为实现16位的指令长度,舍弃了ARM指令集的一些特性,如大多数的Thumb指令是无条件执行的,而几乎所有的ARM指令都是有条件执行的,大多数的Thumb数据处理指令采用2地址格式。

由于Thumb指令的长度为16位,即只用ARM指令一半的位数来实现同样的功能,所以,要实现特定的程序功能,所需的Thumb指令的条数较ARM指令多。

在一般的情况下,Thumb指令与ARM指令的时间效率和空间效率关系为:

●Thumb代码所需的存储空间约为ARM代码的60%~70%。

●Thumb代码使用的指令数比ARM代码多约30%~40%。

●若使用32位的存储器,ARM代码比Thumb代码快约40%。

●若使用16位的存储器,Thumb代码比ARM代码快约40%~50%。

●与ARM代码相比较,使用Thumb代码,存储器的功耗会降低约30%。

显然,ARM指令集和Thumb指令集各有其优点,若对系统的性能有较高要求,应使用32位的存储系统和ARM指令集,若对系统的成本及功耗有较高要求,则应使用16位的存储系统和Thumb指令集。

当然,若两者结合使用,充分发挥其各自的优点,会取得更好的效果。

Thumb指令集与ARM指令集在以下几个方面有区别:

●跳转指令。

条件跳转在范围上有更多的限制,转向子程序只具有无条件转移。

●数据处理指令。

对通用寄存器进行操作,操作结果需放入其中一个操作数寄存器,而不是第三个寄存器。

●单寄存器加载和存储指令。

Thumb状态下,单寄存器加载和存储指令只能访问寄存器R0~R7。

●批量寄存器加载和存储指令。

LDM和STM指令可以将任何范围为R0~R7的寄存器子集加载或存储,PUSH和POP指令使用堆栈指针R13作为基址实现满递减堆栈,除R0~R7外,PUSH指令还可以存储链接寄存器R14,并且POP指令可以加载程序指令PC。

●Thumb指令集没有包含进行异常处理时需要的一些指令,因此,在异常中断时还是需要使用ARM指令。

这种限制决定了Thumb指令不能单独使用需要与ARM指令配合使用。

Thumb寄存器和ARM寄存器之间的关系

Thumb寄存器在ARM寄存器上的映射如图所示。

图Thumb寄存器在ARM寄存器上的映射

1.Thumb状态寄存器集是ARM状态寄存器集的子集

程序员可直接访问8个通用寄存器R0~R7、PC、堆栈指针SP、链接寄存器LR和CPSR。

每个特权模式都有分组的SP、LR和SPSR。

2.Thumb状态寄存器与ARM状态寄存器的关系

Thumb状态寄存器与ARM状态寄存器有如下关系:

●Thumb状态R0~R7与ARM状态R0~R7相同。

●Thumb状态CPSR和SPSR与ARM状态CPSR和SPSR相同。

●Thumb状态SP映射到ARM状态R13。

●Thumb状态LR映射到ARM状态R14。

●Thumb状态PC映射到ARM状态PC(R15)。

3.在Thumb状态中访问高寄存器

在Thumb状态中高寄存器(寄存器R0~R7为低寄存器,寄存器R8~R15为高寄存器)不是标准寄存器集的一部分,汇编语言程序员对它们的访问受到限制,但可以将它们用于快速暂存。

可以使用MOV指令的特殊变量将一个值从低寄存器R0~R7转移到高寄存器R8~R15,或者从高寄存器到低寄存器。

CMP指令可用于比较高寄存器和低寄存器的值。

ADD指令可用于将高寄存器的值与低寄存器的值相加。

3.4.3Thumb指令分类介绍

Thumb指令集分为:

分支指令、数据传送指令、单寄存器加载和存储指令以及多寄存器加载和存储指令。

Thumb指令集没有协处理器指令、信号量(semaphore)指令以及访问CPSR或SPSR的指令。

1.存储器访问指令

(1)LDR和STR——立即数偏移

加载寄存器和存储寄存器。

存储器的地址以一个寄存器的立即数偏移(immediateoffset)指明。

指令格式:

opRd,[Rn,#immed_5×4]

opHRd,[Rn,#immed_5×2]

opBRd,[Rn,#immed_5×1]

其中:

●op:

为LDR或STR。

●H:

指明无符号半字传送的参数。

●B:

指明无符号字节传送的参数。

●Rd:

加载和存储寄存器。

Rd必须在R0~R7范围内。

●Rn:

基址寄存器。

Rn必须在R0~R7范围内。

●immed_5×N:

偏移量。

它是一个表达式,其取值(在汇编时)是N的倍数,在(0~31)*N范围内,N=4、2、1。

●STR:

用于存储一个字、半字或字节到存储器中。

●LDR:

用于从存储器加载一个字、半字或字节。

●Rn:

Rn中的基址加上偏移形成操作数的地址。

立即数偏移的半字和字节加载是无符号的。

数据加载到Rd的最低有效字或字节,Rd的其余位补0。

字传送的地址必须可被4整除,半字传送的地址必须可被2整除。

指令示例:

LDRR3,[R5,#0]

STRBR0,[R3,#31]

STRHR7,[R3,#16]

LDRBR2,[R4,#1abel-{PC}]

(2)LDR和STR——寄存器偏移

加载寄存器和存储寄存器。

用一个寄存器的基于寄存器偏移指明存储器地址。

指令格式:

opRd,[Rn,Rm]

其中,op是下列情况之一:

●LDR:

加载寄存器,4字节字。

●STR:

存储寄存器,4字节字。

●LDRH:

加载寄存器,2字节无符号半字。

●LDRSH:

加载寄存器,2字节带符号半字。

●STRH:

存储寄存器,2字节半字。

●LDRB:

加载寄存器,无符号字节。

●LDRSB:

加载寄存器,带符号字节。

●STRB:

存储寄存器,字节。

●Rm:

内含偏移量的寄存器,Rm必须在R0~R7范围内。

带符号和无符号存储指令没有区别。

STR指令将Rd中的一个字、半字或字节存储到存储器。

LDR指令从存储器中将一个字、半字或字节加载到Rd。

Rn中的基址加上偏移量形成存储器的地址。

寄存器偏移的半字和字节加载可以是带符号或无符号的。

数据加载到Rd的最低有效字或字节。

对于无符号加载,Rd的其余位补0;或对于带符号加载,Rd的其余位复制符号位。

字传送地址必须可被4整除,半字传送地址必须可被2整除。

指令示例:

LDRR2,[Rl,R5]

LDRSHR0,[R0,R6]

STRBRl,[R7,R0]

(3)LDR和STR——PC或SP相对偏移

加载寄存器和存储寄存器。

用PC或SP中值的立即数偏移指明存储器中的地址。

没有PC相对偏移的STR指令。

指令格式:

LDRRd,[PC,#immed_8×4]

LDRRd,[label

LDRRd,[[SP,#immed_8×4]

STRRd,[SP,#immed_8×4]

其中:

●immed_8×4:

偏移量。

它是一个表达式,取值(在汇编时)为4的整数倍,范围在0~1020之间。

●label:

程序相对偏移表达式。

label必须在当前指令之后且1KB范围内。

●STR:

将一个字存储到存储器。

●LDR:

从存储器中加载一个字。

PC或SP的基址加上偏移量形成存储器地址。

PC的位[1]被忽略,这确保了地址是字对准的。

字或半字传送的地址必须是4的整数倍。

指令示例:

LDRR2,[PC,#1016]

LDRR5,localdata

LDRR0,[SP,#920]

STRRl,[SP,#20]

(4)PUSH和POP

低寄存器和可选的LR进栈以及低寄存器和可选的PC出栈。

指令格式:

PUSH{reglist}

POP{reglist}

PUSH{reglist,LR}

POP{reglist,PC}

其中:

●reglist:

低寄存器的全部或其子集。

括号是指令格式的一部分,它们不代表指令列表可选。

列表中至少有1个寄存器。

Thumb堆栈是满递减堆栈,堆栈向下增长,且SP指向堆栈的最后入口。

寄存器以数字顺序存储在堆栈中。

最低数字的寄存器存储在最低地址处。

POP{reglist,PC}这条指令引起处理器转移到从堆栈弹出给PC的地址,这通常是从子程序返回,其中LR在子程序开头压进堆栈。

这些指令不影响条件码标志。

指令示例:

PUSH{R0,R3,R5}

PUSH{R1,R4-R7}

PUSH{R0,LR}

POP{R2,R5}

POP{R0-R7,PC}

(5)LDMIA和STMIA

加载和存储多个寄存器。

指令格式:

opRn!

,{reglist}

其中,op为LDMIA或STMIA。

reglist为低寄存器或低寄存器范围的、用逗号隔开的列表。

括号是指令格式的一部分,它们不代表指令列表可选,列表中至少应有1个寄存器。

寄存器以数字顺序加载或存储,最低数字的寄存器在Rn的初始地址中。

Rn的值以reglist中寄存器个数的4倍增加。

若Rn在寄存器列表中,则:

●对于LDMIA指令,Rn的最终值是加载的值,不是增加后的地址。

●对于STMIA指令,Rn存储的值有两种情况:

若Rn是寄存器列表中最低数字的寄存器,则Rn存储的值为Rn的初值;其他情况则不可预知,当然,reglist中最好不包括Rn。

指令示例:

LDMIAR3!

{R0,R4}

LDMIAR5!

{R0~R7}

STMIAR0!

{R6,R7}

STMIAR3!

{R3,R5,R7}

2.数据处理指令

(1)ADD和SUB——低寄存器

加法和减法。

对于低寄存器操作,这2条指令各有如下3种形式:

●两个寄存器的内容相加或相减,结果放到第3个寄存器中。

●寄存器中的值加上或减去一个小整数,结果放到另一个不同的寄存器中。

●寄存器中的值加上或减去一个大整数,结果放回同一个寄存器中。

指令格式:

opRd,Rn,Rm

opRd,Rn,#expr3

opRd,#expr8

其中:

●op为ADD或SUB。

●Rd:

目的寄存器。

它也用做“opRd,#expr8”的第1个操作数。

●Rn:

第一操作数寄存器。

●Rm:

第二操作数寄存器。

●expr3:

表达式,为取值在-7~+7范围内的整数(3位立即数)。

●expr8:

表达式,为取值在-255~+255范围内的整数(8位立即数)。

“opRd,Rn,Rm”执行Rn+Rm或Rn-Rm操作,结果放在Rd中。

“opRd,Rn,#expr3”执行Rn+expr3或Rn-expr3操作,结果放在Rd中。

“opRd,#expr8”执行Rd+expr8或Rd-expr8操作,结果放在Rd中。

expr3或expr8为负值的ADD指令汇编成相对应的带正数常量的SUB指令。

expr3或expr8为负值的SUB指令汇编成相对应的带正数常量的ADD指令。

Rd、Rn和Rm必须是低寄存器(R0~R7)。

这些指令更新标志N、Z、C和V。

指令示例:

ADDR3,Rl,R5

SUBR0,R4,#5

ADDR7,#201

(2)ADD——高或低寄存器

将寄存器中值相加,结果送回到第一操作数寄存器。

指令格式:

ADDRd,Rm

其中:

●Rd:

目的寄存器,也是第一操作数寄存器。

●Rm:

第二操作数寄存器。

这条指令将Rd和Rm中的值相加,结果放在Rd中。

当Rd和Rm都是低寄存器时,指令“ADDRd,Rm”汇编成指令“ADDRd,Rd,Rm”。

若Rd和Rm是低寄存器,则更新条件码标志N、Z、C和V;其他情况下这些标志不受影响。

指令示例:

ADDR12,R4

(3)ADD和SUB——SP

SP加上或减去立即数常量。

指令格式:

ADDSP,#expr

SUBSP,#expr

其中:

expr为表达式,取值(在汇编时)为在-508~+508范围内的4的整倍数。

该指令把expr的值加到SP的值上或用SP的值减去expr的值,结果放到SP中。

expr为负值的ADD指令汇编成相对应的带正数常量的SUB指令。

expr为负值的SUB指令汇编成相对应的带正数常量的ADD指令。

这条指令不影响条件码标志。

指令示例:

ADDSP,#32

SUBSP,#96

(4)ADD——PC或SP相对偏移

SP或PC值加一立即数常量,结果放入低寄存器。

指令格式:

ADDRd,Rp,#expr

其中:

●Rd:

目的寄存器。

Rd必须在R0~R7范围内。

●Rp:

SP或PC。

●expr:

表达式,取值(汇编时)为在0~1020范围内的4的整倍数。

这条指令把expr加到Rp的值中,结果放入Rd。

若Rp是PC,则使用值是(当前指令地址+4)AND&FFFFFFC,即忽略地址的低2位。

这条指令不影响条件码标志。

指令示例:

ADDR6,SP,#64

ADDR2,PC,#980

(5)ADC、SBC和MUL

带进位的加法、带进位的减法和乘法。

指令格式:

opRd,Rm

其中:

●op为ADC、SBC或MUL。

●Rd:

目的寄存器,也是第一操作数寄存器。

●Rm:

第二操作数寄存器,Rd、Rm必须是低寄存器。

ADC将带进位标志的Rd和Rm的值相加,结果放在Rd中,用这条指令可组合成多字加法。

SBC考虑进位标志,从Rd值中减去Rm的值,结果放入Rd中,用这条指令可组合成多字减法。

MUL进行Rd和Rm值的乘法,结果放入Rd中。

Rd和Rm必须是低寄存器(R0~R7)。

ADC和SBC更新标志N、Z、C和V。

MUL更新标志N和Z。

在ARMv4及以前版本中,MUL会使标志C和V不可靠。

在ARMv5及以后版本中,MUL不影响标志C和V。

指令示例:

ADCR2,R4

SBCR0,R1

MULR7,R6

(6)按位逻辑操作AND、ORR、EOR和BIC

指令格式:

opRd,Rm

其中:

●op为AND、ORR、EOR或BIC。

●Rd:

目的寄存器,它也包含第一操作数,Rd必须在R0~R7范围内。

●Rm:

第二操作数寄存器,Rm必须在R0~R7范围内。

这些指令用于对Rd和Rm中的值进行按位逻辑操作,结果放在Rd中,操作如下:

●AND:

进行逻辑“与”操作。

●ORR:

进行逻辑“或”操作。

●EOR:

进行逻辑“异或”操作。

●BIC:

进行“RdANDNOTRm”操作。

这些指令根据结果更新标志N和Z。

程序示例:

ANDR1,R2

ORR R0,R1

EOR R5,R6

BIC R7,R6

(7)移位和循环移位操作ASR、LSL、LSR和ROR

Thumb指令集中,移位和循环移位操作作为独立的指令使用,这些指令可使用寄存器中的值或立即数移位量。

指令格式:

opRd,Rs

opRd,Rm,#expr

其中:

●op是下列其中之一:

●ASR:

算术右移,将寄存器中的内容看做补码形式的带符号整数。

将符号位复制到空出位。

●LSL:

逻辑左移,空出位填零。

●LSR:

逻辑右移,空出位填零。

●ROR:

循环右移,将寄存器右端移出的位循环移回到左端。

ROR仅能与寄存器控制的移位一起使用。

●Rd:

目的寄存器,它也是寄存器控制移位的源寄存器。

Rd必须在R0~R7范围内。

●Rs:

包含移位量的寄存器,Rs必须在R0~R7范围内。

●Rm:

立即数移位的源寄存器,Rm必须在R0~R7范围内。

●expr:

立即数移位量,它是一个取值(在汇编时)为整数的表达式。

整数的范围为:

若op是LSL,则为0~31;其他情况则为1~32。

对于除ROR以外的所有指令:

●若移位量为32,则Rd清零,最后移出的位保留在标志C中。

●若移位量大于32,则Rd和标志C均被清零。

这些指令根据结果更新标志N和Z,且不影响标志V。

对于标志C,若移位量是零,则不受影响。

其他情况下,它包含源寄存器的最后移出位。

指令示例:

ASRR3,R5

LSRR0,R2,#16 ;将R2的内容逻辑右移16次后,结果放入R0中

LSRR5,R5,av 

(8)比较指令CMP和CMN

指令格式:

CMPRn,#expr

CMPRn,Rm

CMNRn,Rm

其中:

●Rn:

第一操作数寄存器。

●expr:

表达式,其值(在汇编时)为在0~255范围内的整数。

●Rm:

第二操作数寄存器。

CMP指令从Rn的值中减去expr或Rm的值,CMN指令将Rm和Rn的值相加,这些指令根据结果更新标志N、Z、C和V,但不往寄存器中存放结果。

对于“CMPRn,#expr”和CMN指令,Rn和Rm必须在R0~R7范围内。

对于“CMPRn,Rm”指令,Rn和Rm可以是R0~R15中的任何寄存器。

指令示例:

CMPR2,#255

CMPR7,R12

CMNRl,R5

(9)传送、传送非和取负(MOV、MVN和NEG)

指令格式:

MOVRd,#expr

MOVRd,Rm

MVNRd,Rm

NEGRd,Rm

其中:

●Rd:

目的寄存器。

●expr:

表达式,其取值为在0~255范围内的整数。

●Rm:

源寄存器。

MOV指令将#expr或Rm的值放入Rd。

MVN指令从Rm中取值,然后对该值进行按位逻辑“非”操作,结果放入Rd。

NEG指令取Rm的值再乘以-1,结果放入Rd。

对于“MOVRd,#expr”、MVN和NEG指令,Rd和Rm必须在R0~R7范围内。

对于“MOVRd,Rm”指令,Rd和Rm可以是寄存器R0~R15中的任意一个。

“MOVRd,#expr”和MVN指令更新标志N和Z,对标志C或V无影响。

NEG指令更新标志N、Z、C和V。

“MOVRd,Rm”指令中,若Rd或Rm是高寄存器(R8~R18),则标志不受影响;若Rd和Rm都是低寄存器(R0~R7),则更新标志N和Z,且清除标志C和V。

指令示例:

MOVR3,#0

MOVR0,R12

MVNR7,R1

NEGR2,R2

(10)测试位TST

指令格式:

TSTRn,Rm

其中:

●Rn:

第一操作数寄存器。

●Rm:

第二操作数寄存器。

TST对Rm和Rn中的值进行按位“与”操作。

但不把结果放入寄存器。

该指令根据结果更新标志N和Z,标志C和V不受影响。

Rn和Rm必须在R0~R7范围内。

指令示例:

TSTR2,R4

3.分支指令

(1)分支B指令

这是Thumb指令集中唯一的有条件指令。

指令格式:

B{cond}label

其中,label是程序相对偏移表达式,通常是在同一代码块内的标号。

若使用cond,则label必须在当前指令的-256~+256字节范围内。

若指令是无条件的,则label必须在±2KB范围内。

若cond满足或不使用cond,则B指令引起处理器转移到label。

label必须在指定限制内。

ARM链接器不能增加代码来产生更长的转移。

指令示例:

Bdloop

BEGsectB

(2)带链接的长分支BL指令

指令格式:

BLlabel

其中,1abel为程序相对转移表达式。

BL指令将下一条指令的地址复制到R14(链接寄存器),并引起处理器转移到1abel。

BL指令不能转移到当前指令±4MB以外的地址。

必要时,ARM链接器插入代码以允许更长的转移。

指令示例:

BLextract

(3)分支,并可选地切换指令集BX

指令格式:

BX Rm

其中,Rm装有分支目的地址的ARM寄存器。

Rm的位[0]不用于地址部分。

若Rm的位[0]清零,则位[1]也必须清零,指令清除CPSR中的标志T,目的地址的代码被解释为ARM代码,BX指令引起处理器转移到Rm存储的地址。

若Rm的位[0]置位,则指令集切换到Thumb状态。

指令示例:

BX R5

(4)带链接分支,并可选地交换指令集BLX

指令格式:

BLX Rm

BLX label

其中,Rm装有分支目的地址的ARM寄存器。

Rm的位[0]不用于地址部分。

若Rm的位[0]清零,则位[1]必须也清零,指令清除CPSR中的标志T,目的地址的代码被解释为ARM代码。

Label为程序相对偏移表达式,“BLXlabel”始终引起处理器切换到ARM状态。

BLX指令可用于:

●复制下一条指令的地址到R14。

●引起处理器转移到label或Rm存储的地址。

●如果Rm的位[0]清零,或使用“BLXlabel”形式,则指令集切换到ARM状态。

指令不能转移到当前指令±4Mb范围以外的地址。

必要时,ARM链接器插入代码以允许更长的转移。

指令示例:

BLX R6

BLX armsub

4.中断和断点指令

(1)软件中断SWI指令

指令格式:

SWIimmed_8

其中,immed_8为数字表达式,其取值为0~255范围内的整数。

SWI指令引起SWI异常。

这意味着处理器状态切换到ARM态;处理器模式切换到管理模式,CPSR保存到管理模式的SPSR中,执行转移到SWI向量地址。

处理器忽略immed_8,但immed_8出现在指令操作码的位[7:

0]中,而异常处理程序用它来确定正在请求何种服务,这条指令不影响条件码标志。

指令示例:

SWI12

(2)断点BKPT指令

指令格式:

BKPTimmed_8

其中,immed_8为数字表达式,取值为0~255范围内的整数。

BKPT指令引起处理器进入调试模式。

调试工具利用这一点来调查到达特定地址的指令时的系统状态。

尽管immed_8出现在指令操作码的位[7:

0]中,处理器忽略immed_8。

调试器用它来保存有关断点的附加信息。

指令示例:

BKPT67

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

当前位置:首页 > 初中教育 > 政史地

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

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