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

thumb指令分类

 thumb指令集分为:分支指令、数据传送指令、单寄存器加载和存储指令以及多寄存器加载和存储指令。thumb指令集没有协处理器指令、信号量(semaphore)指令以及访问cpsr或spsr的指令。[1]   1. 存储器访问指令  (1)dr和str--立即数偏移  加载寄存器和存储寄存器。存储器的地址以一个寄存器的立即数偏移(immediate offset)指明。  指令格式:  op rd, n,#immed_5×4]  oph rd, n,#immed_5×2]  opb rd, n,#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,5,#0]  strb r0,3,#31]  strh r7,3,#16]  drb r2,4,#1abe-{pc}]  (2)dr和str--寄存器偏移  加载寄存器和存储寄存器。用一个寄存器的基于寄存器偏移指明存储器地址。  指令格式:  op rd,n,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,,r5]  drsh r0,0,r6]  strb r,7,r0]  (3)dr和str--pc或sp相对偏移  加载寄存器和存储寄存器。用pc或sp中值的立即数偏移指明存储器中的地址。没有pc相对偏移的str指令。  指令格式:  dr rd,c,#immed_8×4]  dr rd,be  dr rd,sp,#immed_8×4]  str rd, p,#immed_8×4]  其中:  immed_8×4:偏移量。它是一个表达式,取值(在汇编时)为4的整数倍,范围在0~1020之间。  abe:程序相对偏移表达式。abe必须在当前指令之后且1kb范围内。  str:将一个字存储到存储器。  dr:从存储器中加载一个字。  pc或sp的基址加上偏移量形成存储器地址。pc的位]被忽略,这确保了地址是字对准的。字或半字传送的地址必须是4的整数倍。  指令示例:  dr r2,c,#1016]  dr r5,ocadata  dr r0,p,#920]  str r,p,#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)adc、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{cond} 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的位]不用于地址部分。若rm 的位]清零,则位]也必须清零,指令清除cpsr中的标志t,目的地址的代码被解释为arm代码,bx指令引起处理器转移到rm存储的地址。若rm的位]置位,则指令集切换到thumb状态。  指令示例:  bx  r5  (4)带链接分支,并可选地交换指令集bx  指令格式:  bx  rm  bx  abe  其中,rm 装有分支目的地址的arm寄存器。rm的位]不用于地址部分。若rm 的位]清零,则位]必须也清零,指令清除cpsr中的标志t,目的地址的代码被解释为arm代码。abe为程序相对偏移表达式,“bx abe”始终引起处理器切换到arm状态。  bx指令可用于:  复制下一条指令的地址到r14。  引起处理器转移到abe或rm存储的地址。  如果rm的位]清零,或使用“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出现在指令操作码的位:0]中,而异常处理程序用它来确定正在请求何种服务,这条指令不影响条件码标志。  指令示例:  swi 12  (2)断点bkpt指令  指令格式:  bkpt immed_8  其中,immed_8为数字表达式,取值为0~255范围内的整数。  bkpt指令引起处理器进入调试模式。调试工具利用这一点来调查到达特定地址的指令时的系统状态。尽管immed_8出现在指令操作码的位:0]中,处理器忽略immed_8。调试器用它来保存有关断点的附加信息。  指令示例:  bkpt 67

  • UC3846控制芯片工作原理控制图 逆变焊机原理与用途
  • 数字万用表电阻档测试二极管正反向没有阻值(使用万用表测量二极管的正向电阻,为什么各档)
  • 学单片机需要学数电模电吗(学单片机要先学数电模电吗)
  • 电工怎么选择适合自己用的万用表(电工初学者买什么样的万用表好)
  • 单片机需要同时运行多个任务怎么办(单片机怎么同时执行多个任务)
  • 电机保护的方案取决于负载的机械特性
  • 绝缘电阻表正负搭接不复零位是怎么回事
  • 短路怎么用万用表查