华强电子网

电子元器件原材料
采购平台

Thumb指令

本词条由华强电子网用户提供,如果涉嫌侵权,请与我们客服联系,我们核实后将及时处理。

关键词:

Thumb指令集是ARM指令集的一个子集,是针对代码密度问题而提出的,它具有16位的代码宽度。与等价的32位代码相比较,Thumb指令集在保留32位代码优势的同时,大大的节省了系统的存储空间。Thumb不是一个完整的体系结构,不能指望处理器只执行Thumb指令集而不支持ARM指令集。

Thumb指令分类

  • Thumb指令集分为:分支指令、数据传送指令、单寄存器加载和存储指令以及多寄存器加载和存储指令。Thumb指令集没有协处理器指令、信号量(semaphore)指令以及访问CPSR或SPSR的指令。

    1. 存储器访问指令

    (1)DR和STR--立即数偏移

    加载寄存器和存储寄存器。存储器的地址以一个寄存器的立即数偏移(immediate offset)指明。

    指令格式:

    op Rd, [Rn,#immed_5×4]

    opH Rd, [Rn,#immed_5×2]

    opB Rd, [Rn,#immed_5×1]

    其中:

    op:为DR或STR。

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

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

    Rd:加载和存储寄存器。Rd 必须在R0~R7范围内。

    Rn:基址寄存器。Rn 必须在R0~R7范围内。

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

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

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

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

    立即数偏移的半字和字节加载是无符号的。数据加载到Rd的最低有效字或字节,Rd 的其余位补0。

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

    指令示例:

    DR R3,[R5,#0]

    STRB R0,[R3,#31]

    STRH R7,[R3,#16]

    DRB R2,[R4,#1abe-{PC}]

    (2)DR和STR--寄存器偏移

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

    指令格式:

    op Rd,[Rn,Rm]

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

    DR:加载寄存器,4字节字。

    STR:存储寄存器,4字节字。

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

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

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

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

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

    STRB:存储寄存器,字节。

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

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

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

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

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

    寄存器偏移的半字和字节加载可以是带符号或无符号的。数据加载到Rd的最低有效字或字节。对于无符号加载,Rd的其余位补0;或对于带符号加载,Rd的其余位复制符号位。字传送地址必须可被4整除,半字传送地址必须可被2整除。

    指令示例:

    DR R2,[R,R5]

    DRSH R0,[R0,R6]

    STRB R,[R7,R0]

    (3)DR和STR--PC或SP相对偏移

    加载寄存器和存储寄存器。用PC或SP中值的立即数偏移指明存储器中的地址。没有PC相对偏移的STR指令。

    指令格式:

    DR Rd,[PC,#immed_8×4]

    DR Rd,[abe

    DR Rd,[[SP,#immed_8×4]

    STR Rd, [SP,#immed_8×4]

    其中:

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

    abe:程序相对偏移表达式。abe必须在当前指令之后且1KB范围内。

    STR:将一个字存储到存储器。

    DR:从存储器中加载一个字。

    PC或SP的基址加上偏移量形成存储器地址。PC的位[1]被忽略,这确保了地址是字对准的。字或半字传送的地址必须是4的整数倍。

    指令示例:

    DR R2,[PC,#1016]

    DR R5,ocadata

    DR R0,[SP,#920]

    STR R,[SP,#20]

    (4)PUSH和POP

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

    指令格式:

    PUSH {regist}

    POP {regist}

    PUSH {regist,R}

    POP {regist,PC}

    其中:

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

    括号是指令格式的一部分,它们不代表指令列表可选。列表中至少有1个寄存器。Thumb堆栈是满递减堆栈,堆栈向下增长,且SP指向堆栈的最后入口。寄存器以数字顺序存储在堆栈中。最低数字的寄存器存储在最低地址处。

    POP {regist,PC}这条指令引起处理器转移到从堆栈弹出给PC的地址,这通常是从子程序返回,其中R在子程序开头压进堆栈。这些指令不影响条件码标志。

    指令示例:

    PUSH {R0,R3,R5}

    PUSH {R1,R4-R7}

    PUSH {R0,R}

    POP {R2,R5}

    POP {R0-R7,PC}

    (5)DMIA和STMIA

    加载和存储多个寄存器。

    指令格式:

    op Rn!,{regist}

    其中,op为DMIA或STMIA。

    regist为低寄存器或低寄存器范围的、用逗号隔开的列表。括号是指令格式的一部分,它们不代表指令列表可选,列表中至少应有1个寄存器。寄存器以数字顺序加载或存储,最低数字的寄存器在Rn的初始地址中。

    Rn的值以regist中寄存器个数的4 倍增加。若Rn在寄存器列表中,则:

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

    对于STMIA指令,Rn存储的值有两种情况:若Rn是寄存器列表中最低数字的寄存器,则Rn存储的值为Rn的初值;其他情况则不可预知,当然,regist中最好不包括Rn。

    指令示例:

    DMIA R3!,{R0,R4}

    DMIA R5!,{R0~R7}

    STMIA R0!,{R6,R7}

    STMIA R3!,{R3,R5,R7}

    2. 数据处理指令

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

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

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

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

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

    指令格式:

    op Rd,Rn,Rm

    op Rd,Rn,#expr3

    op Rd,#expr8

    其中:

    op为ADD或SUB。

    Rd:目的寄存器。它也用做“op Rd,#expr8”的第1个操作数。

    Rn:第一操作数寄存器。

    Rm:第二操作数寄存器。

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

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

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

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

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

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

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

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

    指令示例:

    ADD R3,R,R5

    SUB R0,R4,#5

    ADD R7,#201

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

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

    指令格式:

    ADD Rd,Rm

    其中:

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

    Rm:第二操作数寄存器。

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

    当Rd和Rm都是低寄存器时,指令“ADD Rd,Rm”汇编成指令“ADD Rd,Rd,Rm”。若Rd和Rm是低寄存器,则更新条件码标志N、Z、C 和V;其他情况下这些标志不受影响。

    指令示例:

    ADD R12,R4

    (3)ADD和SUB--SP

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

    指令格式:

    ADD SP,#expr

    SUB SP,#expr

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

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

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

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

    指令示例:

    ADD SP,#32

    SUB SP,#96

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

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

    指令格式:

    ADD Rd,Rp,#expr

    其中:

    Rd:目的寄存器。Rd必须在R0~R7范围内。

    Rp:SP 或PC。

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

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

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

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

    指令示例:

    ADD R6,SP,#64

    ADD R2,PC,#980

    (5)、SBC和MU

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

    指令格式:

    op Rd,Rm

    其中:

    op为ADC、SBC或MU。

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

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

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

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

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

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

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

    在ARMv4及以前版本中,MU会使标志C和V不可靠。在ARMv5及以后版本中,MU不影响标志C和V。

    指令示例:

    ADC R2,R4

    SBC R0,R1

    MU R7,R6

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

    指令格式:

    op Rd,Rm

    其中:

    op为AND、ORR、EOR或BIC。

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

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

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

    AND:进行逻辑“与”操作。

    ORR:进行逻辑“或”操作。

    EOR:进行逻辑“异或”操作。

    BIC:进行“Rd AND NOT Rm”操作。

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

    程序示例:

    AND R1,R2

    ORR R0,R1

    EOR R5,R6

    BIC R7,R6

    (7)移位和循环移位操作ASR、S、SR和ROR

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

    指令格式:

    op Rd,Rs

    op Rd,Rm,#expr

    其中:

    op是下列其中之一:

    ASR:算术右移,将寄存器中的内容看做补码形式的带符号整数。将符号位复制到空出位。

    S:逻辑左移,空出位填零。

    SR:逻辑右移,空出位填零。

    ROR:循环右移,将寄存器右端移出的位循环移回到左端。ROR仅能与寄存器控制的移位一起使用。

    Rd:目的寄存器,它也是寄存器控制移位的源寄存器。Rd必须在R0~R7范围内。

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

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

    expr:立即数移位量,它是一个取值(在汇编时)为整数的表达式。整数的范围为:若op是S,则为0~31;其他情况则为1~32。

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

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

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

    这些指令根据结果更新标志N和Z,且不影响标志V。对于标志C,若移位量是零,则不受影响。其他情况下,它包含源寄存器的最后移出位。

    指令示例:

    ASR R3,R5

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

    SR R5,R5,av

    (8)比较指令CMP 和CMN

    指令格式:

    CMP Rn,#expr

    CMP Rn,Rm

    CMN Rn,Rm

    其中:

    Rn:第一操作数寄存器。

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

    Rm:第二操作数寄存器。

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

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

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

    指令示例:

    CMP R2,#255

    CMP R7,R12

    CMN R,R5

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

    指令格式:

    MOV Rd,#expr

    MOV Rd,Rm

    MVN Rd,Rm

    NEG Rd,Rm

    其中:

    Rd:目的寄存器。

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

    Rm:源寄存器。

    MOV指令将#expr或Rm的值放入Rd。MVN指令从Rm中取值,然后对该值进行按位逻辑“非”操作,结果放入Rd。NEG指令取Rm的值再乘以-1,结果放入Rd。

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

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

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

    指令示例:

    MOV R3,#0

    MOV R0,R12

    MVN R7,R1

    NEG R2,R2

    (10)测试位TST

    指令格式:

    TST Rn,Rm

    其中:

    Rn:第一操作数寄存器。

    Rm:第二操作数寄存器。

    TST对Rm和Rn中的值进行按位“与”操作。但不把结果放入寄存器。该指令根据结果更新标志N和Z,标志C和V不受影响。Rn和Rm必须在R0~R7范围内。

    指令示例:

    TST R2,R4

    3. 分支指令

    (1)分支B指令

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

    指令格式:

    B{cd} abe

    其中,abe是程序相对偏移表达式,通常是在同一代码块内的标号。若使用cond,则abe必须在当前指令的-256~+256字节范围内。若指令是无条件的,则abe必须在±2KB范围内。若cond满足或不使用cond,则B指令引起处理器转移到abe。

    abe必须在指定限制内。ARM链接器不能增加代码来产生更长的转移。

    指令示例:

    B doop

    BEG sectB

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

    指令格式:

    B abe

    其中,1abe为程序相对转移表达式。B指令将下一条指令的地址复制到R14(链接寄存器),并引起处理器转移到1abe。

    B指令不能转移到当前指令±4MB以外的地址。必要时,ARM链接器插入代码以允许更长的转移。

    指令示例:

    B extract

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

    指令格式:

    BX  Rm

    其中,Rm装有分支目的地址的ARM寄存器。Rm的位[0]不用于地址部分。若Rm 的位[0]清零,则位[1]也必须清零,指令清除CPSR中的标志T,目的地址的代码被解释为ARM代码,BX指令引起处理器转移到Rm存储的地址。若Rm的位[0]置位,则指令集切换到Thumb状态。

    指令示例:

    BX  R5

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

    指令格式:

    BX  Rm

    BX  abe

    其中,Rm 装有分支目的地址的ARM寄存器。Rm的位[0]不用于地址部分。若Rm 的位[0]清零,则位[1]必须也清零,指令清除CPSR中的标志T,目的地址的代码被解释为ARM代码。abe为程序相对偏移表达式,“BX  abe”始终引起处理器切换到ARM状态。

    BX指令可用于:

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

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

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

    指令不能转移到当前指令±4Mb范围以外的地址。必要时,ARM链接器插入代码以允许更长的转移。

    指令示例:

    BX  R6

    BX  armsub

    4. 中断和断点指令

    (1)软件中断SWI指令

    指令格式:

    SWI immed_8

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

    SWI指令引起SWI异常。这意味着处理器状态切换到ARM态;处理器模式切换到管理模式,CPSR保存到管理模式的SPSR中,执行转移到SWI向量地址。处理器忽略immed_8,但immed_8出现在指令操作码的位[7:0]中,而异常处理程序用它来确定正在请求何种服务,这条指令不影响条件码标志。

    指令示例:

    SWI 12

    (2)断点BKPT指令

    指令格式:

    BKPT immed_8

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

    BKPT指令引起处理器进入调试模式。调试工具利用这一点来调查到达特定地址的指令时的系统状态。尽管immed_8出现在指令操作码的位[7:0]中,处理器忽略immed_8。调试器用它来保存有关断点的附加信息。

    指令示例:

    BKPT 67

Thumb指令特点

  • 1、Thumb指令继承了ARM指令集的许多特点

    Thumb指令也是采用Load/Store结构,有数据处理、数据传送及流控制指令等。

    2、Thumb指令集丢弃了ARM指令集一些特性

    大多数Thumb指令是无条件执行的(除了转移指令B),而所有ARM指令都是条件执行的。许多Thumb数据处理指令采用2地址格式,即目的寄存器与一个源寄存器相同,而大多数ARM数据处理指令采用的是3地址格式(除了64位乘法指令外)。

    3、Thumb异常时表现的一些特点

    所有异常都会使微处理器返回到ARM模式状态,并在ARM的编程模式中处理。由于ARM微处理器字传送地址必须可被4整除(即字对准),半字传送地址必须可被2整除(即半字对准)。而Thumb指令是2个字节长,而不是4个字节,所以,由Thumb执行状态进入异常时其自然偏移与ARM不同。

Thumb状态切换

  • 1、在任何时刻,CPSR的第5位(位T)决定了ARM微处理器执行的是ARM指令流还是Thumb指令流。当T置1,则认为是16位的Thumb指令流;当T置0,则认为是32位的ARM指令流。

    2、进入Thumb模式

    3、进入Thumb指令模式有两种方法:一种是执行一条交换转移指令BX,另一种方法是利用异常返回,也可以把微处理器从ARM模式转换为Thumb模式。

    4、 退出Thumb模式

    退出Thumb指令模式也有两种方法:一种是执行Thumb指令中的交换转移BX指令可以显式的返回到ARM指令流。另一种是利用异常进入ARM指令流 。

Thumb数据处理指令

  • Thumb数据处理指令包括一组高度优化且相当复杂的指令,范围涵盖编译器通常需要的大多数操作。ARM指令支持在单条指令中完成一个操作数的移位及一个ALU操作,但Thumb指令集将移位操作和ALU操作分离为不同的指令。本部分从以下几个方面介绍:

    数据处理指令的二进制编码

    数据处理指令的分类

    ARM指令与Thumb指令比较

    数据处理指令的二进制编码如下图:

    按照数据处理指令的功能,可以将其分为以下几类:

    ADD与SUB—低寄存器加法和减法

    ADD—高或低寄存器

    ADD与SUB—SP

    ADD—PC或SP相对偏移

    ADC,SBC和MUL

    ARM指令与Thumb指令低寄存器比较:

    ARM指令与Thumb指令高寄存器比较:

图册

词条统计

浏览次数:5908

发布求购