首页 > 其他分享 >arm指令集

arm指令集

时间:2022-08-13 12:56:29浏览次数:50  
标签:语法 addr Rd 涵义 指令集 寄存器 Rn arm

1. 跳转指令

    范围:跳转范围在[-32M, 32M]
  • b/bl

      语法:b <cond> des_addr
            bl <cond> des_addr
      涵义:跳转至目标地址des_addr执行
      区别:b    仅仅是跳转
           bl   跳转且保存pc到lr,调用完程序能返回
        
      eg: b Label1       //跳到Label1执行
          bcc Label      //if cpsr_c == 1, then 跳到Label1执行
          bl func_1      //跳到子程序func_1, 执行完返回
    
  • bx

      语法:bx<cond> Rm
      涵义:跑到Rm(dest_addr)执行指令
            if (Rm_bit[0] == 0)
            目标地址为arm指令
            else
            目标地址为thumb指令
    
  • blx

    • blx(1)

      语法:blx<cond> dest_addr
      涵义:跳到dest_addr执行指令
           设置T_flag = 1,thumb指令
           令lr = pc
      
    • blx(2)

      语法:blx<cond> Rm
      涵义:跳到Rm(dest_addr)执行指令
           T_flag = Rm_bit[0],什么指令取决于Rm_bit[0]
           令pc = Rm & 0xfffffffe
             lr = pc
      

范围:可以实现4GB空间任意跳转

  • ldr pc, =0xffffffff

      语法:ldr pc, =0xffffffff
      涵义:跳到0xffffffff执行
           如果前面指令为 mov lr, pc  则可以实现子程序调用
    

2. 数据处理指令

  • mov

      语法:mov<cond> S Rd, shift_operand
      涵义:Rd = shift_operand
            <cond>:条件码,1则执行,0则不执行;<cond>nd则为无条件执行
            S:有S则更新CPSR相应位,无则不更新
            Rd:目标寄存器
            shift_operand:向Rd中传送的数据,有相应的计算方法
        
      eg: mov    ip, sp
          mov    sp, #868220928
    
  • mvn

      语法:mvn<cond> S Rd, shift_operand
      涵义:Rd = ~shift_operand
        
      用途: 1. Rd = 一个负数
            2. 生成位掩码
            3. 求一个数的反码
        
      eg: mvn r2, #11
    

  • add

      语法:add<cond> S Rd, Rn, shift_operand
      涵义:Rd = Rn + shift_operand, 根据结果更新CPSR条件位
    
  • adc

      语法:adc<cond> S Rd, Rn, shift_operand
      涵义:Rd = Rn + shift_operand + C_flag, 根据结果更新CPSR条件位
        
      add和adc联用可以实现2个64位数相加
      eg: adds r4, r0, r2
          adc r5, r1, r3
          其中:r0, r1存放一个64位数,r0 = low_32bit
               r2, r3存放一个64位数,r2 = low_32bit
      eg: add r3, r0, r3
          add r3, r3, #48     //r3 = r3 + #48
          add Rs, pc, offset  //生成基于pc的跳转指针
    
  • sub

      语法:sub<cond> S Rd, Rn, shift_operand
      涵义:Rd = Rn - shift_operand, 根据结果更新CPSR条件位
        
      eg: sub    fp, ip, #4
          sub    r0, r4, #4
    
  • sbc

      语法:sbc<cond> S Rd, Rn, shift_operand
      涵义:Rd = Rn - shift_operand - ~(C_flag), 根据结果更新CPSR条件位
        
      类似的:sub和sbc联用可以实现2个64位数相减
    
  • rsb

      语法:rsb<cond> S Rd, Rn, shift_operand
      涵义:Rd = shift_operand - Rn, 根据结果更新CPSR条件位
    
  • rsc

      语法:rsc<cond> S Rd, Rn, shift_operand
      涵义:Rd = shift_operand - Rn - ~(C_flag), 根据结果更新CPSR条件位
        
      类似的:rsb和rsc联用可以实现求1个64位数的负数
      eg: rsbs r2, r0, #0
          rsc r3, r1, #0
          其中:64位数存放在r0, r1, r0 = low_32bit
                负数存放在  r2, r3, r2 = low_32bit
    

  • and

      语法:and<cond> S Rd, Rn, shift_operand
      涵义:Rd = Rn & shift_operand, 根据结果更新CPSR条件位
      用于提取Rn中某几位的值
    
  • orr

      语法:orr<cond> S Rd, Rn, shift_operand
      涵义:Rd = Rn | shift_operand, 根据结果更新CPSR条件位
      用于将寄存器中的某些位设为1
        
      eg: mov r0, r2, lsr #24     //将r2的高8位送入r0, r0的高24位为0
          orr r3, r0, r3, lsl #8  //r3 << 8, r3低8位为0, orr操作将r0低8位送入r3
    
  • eor

      语法:eor<cond> S Rd, Rn, shift_operand
      涵义:Rd = Rn ^ shift_operand, 根据结果更新CPSR条件位
      用于将寄存器中的某些位取反
    
  • bic

      语法:bic<cond> S Rd, Rn, shift_operand
      涵义:Rd = Rn & ~shift_operand, 根据结果更新CPSR条件位
      用于将Rn中某几位值清零
        
      eg: bic R0, R0 , #0xF0000000     //将R0高4位清零
    

  • cmp

      语法:cmp<cond> S Rn, shift_operand
      涵义:Result = Rn - shift_operand, 根据Result更新CPSR相应条件位,则后面的指令就能根据CPSR状态执行了
    
  • cmn

      语法:cmn<cond> S Rn, shift_operand
      涵义:Result = Rn + shift_operand, 根据Result更新CPSR相应条件位,则后面的指令就能根据CPSR状态执行了
    
  • tst

      语法:tst<cond> S Rn, shift_operand
      涵义:Result = Rn & shift_operand, 根据Result更新CPSR相应条件位,则后面的指令就能根据CPSR状态执行了
        
      用于检测寄存器中某些位是0 或 1
    
  • teq

      语法:teq<cond> S Rn, shift_operand
      涵义:Result = Rn ^ shift_operand, 根据Result更新CPSR相应条件位,则后面的指令就能根据CPSR状态执行了
        
      用途:1. 比较2个数是否相等,该操作不影响CPSR的V_flag, C_flag
           2. 比较2个数符号是否相同,该操作执行后,CPSR中N_flag为2个数符号位异或结果
    

3. 乘法指令

  • mul

      语法:mul<cond> S Rd, Rm, Rs
      涵义:Rd = Rm * Rs, 根据结果更新CPSR条件位
            S:有则设置CPSR的N_flag, Z_flag
      用途:2个32位数(unsigned or signed)相乘,结果为64位,但只保存低32位,所以结果对于unsigned or signed一样
    
  • mla

      语法:mla<cond> S Rd, Rm, Rs, Rn
      涵义:Rd = Rm * Rs + Rn, 根据结果更新CPSR条件位
            S:有则设置CPSR的N_flag, Z_flag
      用途:2个32位数(unsigned or signed)相乘再加上1个32位数,结果为64位,但只保存低32位,所以结果对于unsigned or signed一样
    

  • smull (signed)

      语法:smull<cond> S RdLo, RdHi, Rm, Rs
      涵义:RdHi = (Rm * Rs)[63:32]
            RdLo = (Rm * Rs)[31:0]
            根据结果更新CPSR条件位
    
  • smlal (signed)

      语法:smulal<cond> S RdLo, RdHi, Rm, Rs
      涵义:RdHi = (Rm * Rs)[63:32] + RdHi + C_flag
            RdLo = (Rm * Rs)[31:0] + RdLo
            RdHi:执行前,保存加数的高32位;执行后,保存结果的高32位
            RdLo:执行前,保存加数的低32位;执行后,保存结果的低32位
            根据结果更新CPSR条件位
    
  • umull (unsigned)

      语法:umull<cond> S RdLo, RdHi, Rm, Rs
      涵义:RdHi = (Rm * Rs)[63:32]
            RdLo = (Rm * Rs)[31:0]
        
            根据结果更新CPSR条件位
    
  • umlal (unsigned)

      语法:umulal<cond> S RdLo, RdHi, Rm, Rs
      涵义:RdHi = (Rm * Rs)[63:32] + RdHi + C_flag
            RdLo = (Rm * Rs)[31:0] + RdLo
            RdHi:执行前,保存加数的高32位;执行后,保存结果的高32位
            RdLo:执行前,保存加数的低32位;执行后,保存结果的低32位
            根据结果更新CPSR条件位
    

4. 杂类算术指令

  • clz

      语法:clz <cond> Rd, Rm
      涵义:计算Rd的前导0的个数
           eg: 0x80000000, clz运算后, Rd = 0
               0x10000000, clz运算后, Rd = 3
    

5. 状态register访问指令

  • mrs

      语法:mrs <cond> Rd, cpsr
           mrs <cond> Rd, spsr
      涵义:读状态寄存器cpsr的值到通用寄存器Rd中
           if (R == 1)
               Rd = spsr
           else
               Rd = cpsr
    
  • msr

      语法: msr<cond> cpsr_<field>, Rm
            msr<cond> cpsr_<field>, #immediate
            msr<cond> spsr_<field>, Rm
            msr<cond> spsr_<field>, #immediate
      涵义:将寄存器值或立即数写入状态寄存器cpsr/spsr相应的field(fsxc)区域中
            if (R == 1)
                spsr = operand
            else
                cpsr = operand
    
      eg: mrs, r0, cpsr       
          bic r0, r0, #0x1f    //清空处理器模式位
          orr r0, r0, #0x13    //设置为特权模式
          msr cpsr_c, r0       //写回,仅仅修改控制位
    
      note: 1. 当进程切换到应用场合时,应指定spsr_fsxc, 保证arm以后扩展未用位,程序也能正常运行
            2. 可以用立即数方式的msr指令修改状态寄存器的条件位域(例外)
    

6. load/store内存访问指令

  • ldr
    语法:ldr<cond> Rd, addr_mode
    涵义:Rd = addr中的值  
         addr_mode: 指令的寻址方式 

         从内存中读取1个32位的字到目标寄存器Rd中
         若,Rd = pc, 则程序跳到目标地址执行
    note: 若指令地址不是字对齐,则读出的value需循环右移n位,n = 8*(寻址方式确定的地址的bit[1:0])

    eg: ldr r0, [r1, #4]            //r0 = r1 + 4
        ldr r0, [r1, #-4]           //r0 = r1 - 4
        ldr r0, [r1, r2 lsl #2]     //r0 = r1 + r2*4
                                      lsl: 逻辑左移2位
        -------------------------------------------
        ldr r0, [r1, #4]!           //r0 = r1 + 4 且 r1 += 4
        ldr r0, [r1, r2 lsl #2]!    //r0 = r1 + r2*4 且 r1 += r2*4
        ldr r0, [r1], #4            //r0 = r1 + 4 且 r1 += 4
        ldr r0, [r1], r2, lsl #2    //r0 = r1 + r2*4 且 r1 += r2*4
  • ldrt
    语法:ldr<cond>t Rd, post_indexed_addr_mode
    涵义:Rd = addr中的值   
         从内存中读取1个32位的字到目标寄存器Rd中
    note: 若指令地址不是字对齐,则读出的value需循环右移n位,n = 8*(寻址方式确定的地址的bit[1:0])
    用途:当cpu在特权模式下,需要按usr mode访问内存,则用ldrt
  • ldrb
    语法:ldr<cond>b Rd, addr_mode
    涵义:Rd = addr中的值   
         从内存中读取1个8位的字节数据到目标寄存器Rd中,且将高24位清零
         若,Rd = pc, 则程序跳到目标地址执行
  • ldrbt
    语法:ldr<cond>bt Rd, post_indexed_addr_mode
    涵义:Rd = addr中的值   
         从内存中读取1个8位的字节数据到目标寄存器Rd中,且将高24位清零
    用途:当cpu在特权模式下,需要按usr mode访问内存,则用ldrbt
  • ldrh
    语法:ldr<cond>h Rd, addr_mode
    涵义:Rd = addr中的值   
         从内存中读取1个16位的半字数据到目标寄存器Rd中,且将高16位清零
         若指令中地址不是半字对齐,则将产生不可预知结果
         若,Rd = pc, 则程序跳到目标地址执行
  • ldrsb
    语法:ldr<cond>sb Rd, addr_mode
    涵义:Rd = addr中的值   
         从内存中读取1个signed 8位的字节数据到目标寄存器Rd中,且将高24位设为该字节数据符号位的值
         若,Rd = pc, 则程序跳到目标地址执行
  • ldrsh
    语法:ldr<cond>sh Rd, addr_mode
    涵义:Rd = addr中的值   
         从内存中读取1个signed 16位的半字数据到目标寄存器Rd中,且将高16位设为该字节数据符号位的值
         若指令中地址不是半字对齐,则将产生不可预知结果
         若,Rd = pc, 则程序跳到目标地址执行

  • str
    语法:str<cond> Rd, addr_mode
    涵义:addr = Rd
         将1个32位的字数据放入addr_mode的内存中
    eg: str r0, [r1, #100]        //r1+100 = r0
        str r0, [r1] #8           //r1 += 8, r1 = r0
  • strb
    语法:str<cond>b Rd, addr_mode
    涵义:addr = Rd[7:0]
         将Rd中低8位的字节数据放入addr_mode的内存中
  • strh
    语法:str<cond>h Rd, addr_mode
    涵义:addr = Rd[15:0]
         将Rd中低16位的字节数据放入addr_mode的内存中
    note: 若指令地址不是半字对齐,则结果不可预测
  • strt
    语法:str<cond>t Rd, addr_mode
    涵义:addr = Rd
         将1个32位的字数据放入addr_mode的内存中
    用途:当cpu在特权模式下,需要按usr mode写内存
  • strbt
    语法:str<cond>bt Rd, addr_mode
    涵义:addr = Rd[7:0]
         将Rd中低8位的字节数据放入addr_mode的内存中
    用途:当cpu在特权模式下,需要按usr mode写内存

7. 批量load/store内存访问指令

  • ldm(1) —— 批量内存字数据read
    语法:ldm<cond> addr_mode Rn!, <registers>
    涵义:将以Rn为基地址的内存中的数据保存至<registers>中

         Rn:为指令寻址模式中的基址寄存器,存放地址块的最低地址
         ! :设置指令中的W位,令指令执行后,将操作数的内存addr写入Rn
         <registers>:寄存器列表,其与内存单元的对应关系为:低编号reg对应低地址单元,高编号reg对应
                     高地址单元
    用途:用于块数据的读取、数据栈操作、从子程序返回的操作
  • ldm(2) —— usr mode 批量内存字数据read
    语法:ldm<cond> addr_mode Rn, <registers_no_PC>^
    涵义:将以Rn为基地址的内存中的数据保存至<registers_no_PC>中

         Rn:为指令寻址模式中的基址寄存器,存放地址块的最低地址
         ^ :在不含pc时,指示指令中所用的寄存器为usr mode下的寄存器
         <registers_no_PC>:寄存器列表不能包含pc,其与内存单元的对应关系为:低编号reg对应低地址单元,高编号reg对应高地址单元
    用途:用于块数据的读取、数据栈操作、从子程序返回的操作
         当cpu在特权模式下,需要按usr mode写内存

    note: 1. 本指令后面不能紧跟访问banked_register, 最好跟一条NOP指令
          2. 执行时,指令中基址寄存器为当前cpu模式下的寄存器
          3. 本指令忽略指令中内存地址低2位,不像ldm(1)需要循环右移
  • ldm(3) —— 带状态register的批量内存字数据read
    语法:ldm<cond> addr_mode Rn!, <registers_with_pc>^
    涵义:Rn:为指令寻址模式中的基址寄存器,存放地址块的最低地址
         ! :设置指令中的W位,令指令执行后,将操作数的内存addr写入Rn
         <registers_with_pc>:寄存器列表中必须包含pc, 否则就是ldm(2); 其与内存单元的对应关系为:低编号reg对应低地址单元,高编号reg对应高地址单元
         ^ :将当前模式下的spsr恢复至cpsr中

    用途:用于块数据的读取、数据栈操作、从子程序返回的操作

  • stm(1) —— 批量内存字数据write
    语法:stm<cond> addr_mode Rn!, <registers>
    涵义:将<registers>中的数据保存至以Rn为基地址的内存中
    用途:用于块数据的写入、数据栈操作、进入子程序的操作
  • stm(2) —— usr mode 批量内存字数据write
    语法:stm<cond> addr_mode Rn, <registers>^
    涵义:将<registers>中的数据保存至以Rn为基地址的内存中

         Rn:为指令寻址模式中的基址寄存器,存放地址块的最低地址
         ^ :在不含pc时,指示指令中所用的寄存器为usr mode下的寄存器
         <registers>:寄存器列表,其与内存单元的对应关系为:低编号reg对应低地址单元,高编号reg对应高地址单元

    用途:用于块数据的写入、数据栈操作、进入子程序的操作

    note: 1. 本指令后面不能紧跟访问banked_register, 最好跟一条NOP指令
          2. 执行时,指令中基址寄存器为当前cpu模式下的寄存器

8. 信号量操作指令

  • swp
    语法:swp<cond> Rd, Rm, [Rn]
    涵义:[Rn] = Rm, Rd = [Rn], 操作单位为字,如果内存地址不是字对齐,需要循环右移n位,n = 8*(Rn[1:0])

         Rd: 目标寄存器
         Rm: 寄存器中包含将要保存到内存中的值
         [Rn]: 要访问的内存地址

    eg: swp r1, r2, [r3]        //r1 = [r3], [r3] = r2
        swp r1, r1, [r2]        //r1, [r2]中数据互换
  • swpb
    语法:swpb<cond> Rd, Rm, [Rn]
    涵义:[Rn] = Rm, Rd = [Rn], 操作单位为byte, 8位

    eg: swpb r1, r2, [r3]        //r1 = [r3], 将r1的高24位清零
                                   [r3] = r2[7:0]

9. 异常中断产生指令

  • swi
    语法:swi<cond> immed_24
    涵义:软中断指令,引发 immed_24 号软中断,执行相应的服务程序
         通常有2种方法:1. immed_24指定服务类型,参数用通用寄存器传递
                      2. immed_24被ignore, r0决定服务类型,参数用其它通用寄存器传递
         immed_24:24位立即数,用来让系统判断请求的服务类型
  • bkpt
    语法:bkpt immed_16
    涵义:软件断点中断指令

         immed_16:16位立即数,其被调试软件用来保存额外的断点信息

    用途:主要供软件调试程序使用

10. arm协处理器指令

  • 协处理器

    arm支持16个协处理器。

    在程序执行过程中,每个协处理器会忽略arm处理器和其它协处理器的指令。当一个协处理器不能执行属于它的协处理器指令时,将产生未定义指令异常 und,在该异常中断处理程序中,可以通过软件模拟该硬件操作。

  • cdp

    语法:cdp<cond> ID, op1, CRd, CRn, CRm, op2
         cdp2 ID, op1, CRd, CRn, CRm, op2
    涵义:本指令让arm处理器通知arm协处理器执行特定的操作,该操作不涉及arm寄存器和内存单元
         若协处理器不能完成,则触发und

         cpd2格式中,<cond>为0b1111,指令为无条件执行指令
         ID: 协处理器的编码
         op1:协处理器将执行的操作的操作码
         op2:协处理器将执行的操作的操作码
         CRd:作为目标寄存器的协处理器寄存器
         CRn:存入第1个操作数的协处理器寄存器
         CRm:存入第1个操作数的协处理器寄存器

    eg: cdp p5, 2, c12, c10, c3, 4    //协处理器p5的初始化操作
                                        其中,op1 = 2, op2 = 4
                                        目标寄存器为c12
                                        源操作数寄存器为c10, c3
  • ldc
    语法:ldc<cond>L ID, CRd, addr_mode
         ldc2L ID, CRd, addr_mode
    涵义:一系列连续的内存单元中将数据 --> 协处理器寄存器中,如不能执行该操作,则触发und

         L: 指示指令为长读取操作,eg: 用于双精度的数据传送

    eg: ldc p6, CR4, [r2, #4]    //CR4 = [r2+4]
                                   r2为arm寄存器
                                   CR4是协处理器p6的寄存器
  • stc
    语法:stc<cond>L ID, CRd, addr_mode
         stc2L ID CRd, addr_mode
    涵义:协处理器的寄存器的数据 --> 一系列连续的内存单元中,如不能执行该操作,则触发und

    eg: stc p8, CR8, [r2, #4]!    //[r2+4] = CR8, r2 += 4
  • mcr
    语法:mcr<cond> ID, op1, Rd, CRn, CRm, op2
         mcr2 ID, op1, Rd, CRn, CRm, op2
    涵义:arm处理器的寄存器的数据 --> 协处理器的寄存器,如不能执行该操作,则触发und

          Rd: arm寄存器
         CRn: 目标寄存器,为协处理器寄存器
         CRm: 附加的目标寄存器或源操作数寄存器

    eg: mcr p14, 3, r7, c7, c11, 6    //r7 -> c7, c11
                                        操作码1:3
                                        操作码2:6
  • mrc
    语法:mrc<cond> ID, op1, Rd, CRn, CRm, op2
         mrc2 ID, op1, Rd, CRn, CRm, op2
    涵义:协处理器的寄存器的数据 --> arm处理器的寄存器,如不能执行该操作,则触发und

          Rd: arm寄存器
         CRn: 目标寄存器, 为协处理器寄存器
         CRm: 附加的目标寄存器或源操作数寄存器

     eg: mrc p15, 2, r5, c0, c2, 4    //c0, c2 -> r5

标签:语法,addr,Rd,涵义,指令集,寄存器,Rn,arm
From: https://www.cnblogs.com/rogerg6/p/16582798.html

相关文章