zoukankan      html  css  js  c++  java
  • ARM汇编基础概述

    ARM与 x86相比较

    ■ 精简指令集

    对于每一个复杂的操作,与x86汇编相比具有更多的指令。

    ■ 固定的指令长度

    x86有可变长度的指令, ARM将指令长度固定为32

    ■ 内存对齐

    ARM/RISC要求内存对齐 

    对齐内存需要进行填充

    ■ 条件执行

     每条指令的前四位包含一个条件码**

    ARM指令的表示方式

    ADDEQS R0,R1,#8为例,其二进制代码形式为:

    3128

    2725

    24—21

    20

    19—16

    15—12

    11—0

    0000

    001

    0100

    1

    0001

    0000

    000000001000

    cond

    Opcode

    Rn

    Rd

    Op2

    从上面可知,ARM指令一般包括5个域:

    条件码域

    cond

    4

    指令代码域

    Opcode

    8

    地址基址

    Rn

    4

    目标或源寄存器

    Rd

    4

    地址偏移或操作寄存器

    Op2

    12

     

    汇编指令格式

    <opcode>{<cond>}{S}{.W|.N}<Rd>,<Rn>{,<operand2>}
    
    <>表示该内容必不可少,{}表示可省略。
    
    <opcode>表示操作码,如ADD表示算术加法。
    
    {<cond>}  表示指令执行的条件域,如EQ,NE等。缺省则表示默认条件(无条件执行)。
    
    {S}      决定指令的执行结果是否影响CPSR的值,使用该后缀则指令执行的结果影响CPSR的值,否则不影响。
    
    {.W|.N}  
    
      使用.W 宽度说明符。 即使 16 位编码可用,该指令宽度说明符也会强制汇编器生成 32 位编码。无论代码将会被汇编为 ARM 代码还是 Thumb(ARMv6T2 或更高版本)代码,您都可在其中使用 .W 说明符。 .W 说明符不会对代码的 ARM 编译产生任何影响。
    
      如果要将指令汇编为 16 位编码,则您可使用 .N 宽度说明符。 在这种情况下,如果指令无法编码为 16 位,或者要将代码汇编为 ARM 代码,则汇编器会生成错误。
    
      使用指令宽度说明符时,必须将说明符紧随在指令助记符和条件代码(如果有)之后,例如:
        BCS.W   label   ; forces 32-bit instruction even for a short branch
    
        B.N     label   : faults if label out of range for 16-bit instruction
    
    
    <Rd>      表示目的寄存器。
    
    <Rn>      表示第一个操作数,为寄存器。
    
    <Op2>      表示第二个操作数,可以使立即数,寄存器或寄存器偏移操作数。

    上述指令ADDEQS R0R1#8;其中操作码为ADD,条件域为EQS表示该指令的执行影响CPSR寄存器的值,R0为目的寄存器,R1为第一个操作数寄存器,立即数#8为第二个操作数。

     

    条件码助记符

    标志位

    含有

    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=1Z=0

    无符号数大于

    LS

    C=0Z=1

    无符号数小于或等于

    GE

    N=V

    带符号数大于或等于

    LT

    N!=V

    带符号数小于

    GT

    Z=0N=V

    带符号数大于

    LE

    Z=1N!=V

    带符号数小于或等于

    AL

    忽略

    无条件执行

    ARM指令

    ADC指令:带进位加法指令,将操作数2的数据与Rn的值相加,再加上CPSR中C条件标志位,结果保存到Rd中

    使用ADC指令实现64位加法

    ADDS R0,R0,R2   ; R0+R2 => R0,影响CPSR中的值 
    
    ADC  R1,R1,R3   ;(R1、R0) = (R1、R0)+(R3、R2)

    SBC指令:带借位减法指令,用寄存器Rn减去操作数2,再减去CPSR中的C条件标志位的非(即若C标志清零,则结果减去1),结果保存在Rd中。

    使用SBC实现64位减法:

    SUBS R0,R0,R2 
    
    SBC  R1,R1,R3  ;使用SBC实现64位减法,(R1,R0) - (R3,R2)

    AND指令:按位与操作

    ANDS R0,R0,#0x01  ;取出最低位数据

    ORR指令:按位或操作

    ORR R0,R0,#0x0F   ;将R0的低4位置1

    EOR指令是进行异或操作,BIC指令是位清除指令(遇1清0)。
    TST:位测试指令

    TST R0,#0x01     ; 判断R0的最低位是否是为0

    TEQ:相等测试指令

    TEQ R0,R1     ; 比较R0与R1是否相等,也可看作相减,相等则为0,Z=1

    MUL指令:乘法指令

    MUL R1,R2,R3   ; R1=R2*R3 
    
    MULS R0,R3,R7  ; R0=R3*R7,同时设置CPSR中的N位和Z位

    MLA是乘加指令,将操作数1和操作数2相乘再加上第3个操作数,结果的低32位存入到Rd中。

    UMULL是64位无符号乘法指令:

    UMULL R0,R1,R5,R8   ; (R1、R0) = R5 * R8

    BL指令:带链接的跳转指令,指令将下一条指令拷贝到R14(即LR)链接寄存器中,然后跳转到指定地址运行 BL指令用于子程序调用,例如:BL DELAY 。

    BX指令:带状态切换的跳转指令,例如 BX R0 ;跳转到R0指定的地址,并根据R0的最低位来切换处理器的状态。

    详细的指令介绍http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/CIHDDCIF.html

    Thumb指令

    Thumb指令可以看作是ARM指令压缩形式的子集,是针对代码密度问题而提出的,具有16位的代码密度。ARM状态下,绝大多数的指令都是有条件执行的。

    而在Thumb状态下,仅有分支指令是有条件执行的。

    Thumb状态下,不能直接访问所有的寄存器,只有寄存器R0R7是可以被任意访问的。寄存器R8R12只能通过MOVADDCMP指令来访问。CMP指令和所有操作R0R7的数据处理指令都会影响CPSR中的条件标志。

    寄存器使用规则

    寄存器的使用必须满足以下规则:

    子程序间通过寄存器R0-R3来传递参数,使用R4-R11来保存局部变量。在Thumb程序中,通常只使用R4-R7来保存局部变量。R12用作子程序间scratch寄存器。

    R13用作数据栈指针,记SP,在子程序中不能用作其它用途SP在进入子程序时的值与退出子程序时的值必须相等。

    R14为连接寄存器,用于保存子程序的返回地址,记作LR如果子程序保存了返回地址,则可以用于其它用途。

    R15为程序计数器,记作PC,不能用作其它用途。

    寄存器

    别名

    特殊名称

    使用规则

    R0

    A1

     

    参数/返回值/ Scratch寄存器1

    R1

    A2

     

    参数/第二个32位的返回值/ Scratch寄存器2

    R2/R3

    A3/A4

     

    参数/ Scratch寄存器3/4

    R4

    V1

     

    ARM状态局部变量寄存器1

    R5

    V2

     

    ARM状态局部变量寄存器2

    R6

    V3

     

    ARM状态局部变量寄存器3

    R7

    V4

     

    ARM状态局部变量寄存器4

    R8

    V5

     

    ARM状态局部变量寄存器5

    R9

    V6

    SB

    ARM状态局部变量寄存器6/基址寄存器

    R10

    V7

    SL

    ARM状态局部变量寄存器7/数据栈限制指针

    R11

    V8

    FP

    ARM状态局部变量寄存器8/ARM帧指针

    R12

     

    IP 

    子程序内部调用的Scratch寄存器

    R13

     

    SP

    堆栈指针

    R14

     

    LR

    连接寄存器(保存子程序返回地址)

    R15

     

    PC

    程序计数器

    CPU总是按照PC的指向对指令序列进行取指、译码和执行,也就是说,最终是PC决定了程序运行流向。故而,程序计数器(PC)属于特别功能寄存器范畴,不能自由地用于存储其他运算数据。

    在程序开始执行前,将程序指令序列的起始地址,即程序的第一条指令所在的内存单元地址送入PCCPU按照PC的指示从内存读取第一条指令(取指)。当执行指令时,CPU自动地修改PC的内容,即每执行一条指令PC增加一个量,这个量等于指令所含的字节数(指令字节数),使PC总是指向下一条将要取指的指令地址由于大多数指令都是按顺序来执行的,所以修改PC的过程通常只是简单的对PC加“指令节数”。

    当程序转移时,转移指令执行的最终结果就是要改变PC的值,此PC值就是转去的目标地址。处理器总是按照PC指向取指、译码、执行,以此实现了程序转移。

    ARM将指令长度固定为32位,故指令字节数总是为4字节。 

    CPSR( Current Program Status Register当前程序状态寄存器)

    ■ 高四位包含条件标志: Negative, Zero, Carry, oVerflow

    ■ 低8位为控制位。

    ■ SPSR( Saved Program Status Register备份的程序状态寄存器) (异常模式)

    CPSR 

    说明:
    条件标识位[31 : 28]:它们的内容可被算术或逻辑运算的结果所改变,并且可以决定某条指令是否被执行。在ARM状态下,绝大多数指令都是有条件的执行的,在Thumb状态下,只有分支指令被有条件的执行

    标志位

    含义

    N

    当用两个补码表示的带符号数进行运算时,N=1 表示运算的结果为负数;N=0 表示运算的结果为正数或零

     Z

    Z=1 表示运算的结果为零;Z=0表示运算的结果为非零

    C

    可以有4种方法设置C的值:

    ─ 加法运算(包括比较指令CMN):当运算结果产生了进位时(无符号数溢出),C=1,否则C=0

    ─ 减法运算(包括比较指令CMP):当运算时产生了借位(无符号数溢出),C=0,否则C=1

    ─ 对于包含移位操作的非加/减运算指令,C为移出值的最后一位。

    ─ 对于其他的非加/减运算指令,C的值通常不改变。

    V

    可以有2种方法设置V的值:

    ─ 对于加/减法运算指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1表示符号位溢出。

    ─ 对于其他的非加/减运算指令,V的值通常不改变。

    保留位[27 : 8]:当改变PSR中的条件码标志位或者控制位时,保留位不要被改变,在程序中也不要使用保留位来存储数据。保留位将用于ARM版本的扩展。
    控制位[7 : 0]PSR的低8位(包括IFTM[40])称为控制位,当发生异常时这些位可以被改变。如果处理器运行特权模式,这些位也可以由程序修改。 

    I

    I =1 表示禁止外部(硬件)中断(IRQ

    F

    F=1 表示快速中断(FIQ

    T

    反映处理器的运行状态

    运行模式位M[4 : 0]M0M1M2M3M4是模式位。这些位决定了处理器的运行模式。

    ARM处理器的七种工作模式

    用户模式(usrARM处理器正常的程序执行状态。

    快速中断模式(fiq:用于高速数据传输或通道处理。

    外部中断模式(irq:用于通用的中断处理。

    管理模式(svc:运行系统级代码来访问硬件或运行操作系统调用的保护模式。

    终止模式(abt:当数据或指令从无效的内存区域取值时进入该模式,用于虚拟存储及存储保护。

    未定义指令模式(und:当未定义的指令执行时进入该模式,用于支持硬件协处理器的软件仿真。

    系统模式(sys:运行具有特权的操作系统任务。

    除用户模式外,其余六种模式称为非用户模式或特权模式。除用户模式和系统模式以外的五种模式又被称为异常模式,常用于处理中断或异常,以及需要访问受保护的系统资源等情况。

    大多数应用程序运行在用户模式下,运行在用户模式下的某些被保护的系统资源是不能被访问的。应用程序也不能直接进行处理器模式的转换,除非产生异常处理,在异常处理中进行处理器模式切换。

    当应用程序发生异常中断时,处理器进入相应的异常模式。在每一种异常模式中都有一组寄存器,供相应的异常处理程序使用,这样就可以保证在进入异常模式时,用户模式下的寄存器(保存了程序运行状态)不被破坏。

    系统模式并不是通过异常过程进入的,它和用户模式具有完全一样的寄存器。但是系统模式属于特权模式,可以访问所有的系统资源,也可以直接进行处理器模式切换。它主要供操作系统任务使用。

    M[4:0]

    处理器模式

    可访问的寄存器

    10000

    用户模式

    PCCPSRR0-R14

    10001

    FIQ模式

    PCCPSRSPSR_fiqR14_fiq-R8_fiqR7-R0

    10010

    IRQ模式

    PCCPSRSPSR_irqR14_irqR13_irqR12-R0

    10011

    管理模式

    PCCPSRSPSR_svcR14_svcR13_svcR12-R0

    10111

    中止模式

    PCCPSRSPSR_abtR14_abtR13_abtR12-R0

    11011

    未定义模式

    PCCPSRSPSR_undR14_undR13_undR12-R0

    11111

    系统模式

    PCCPSRR14-R0

     

      在实际系统中,内核状态需要经常的切换(Interworking)来满足系统性能需求。具体的切换是通过Branch Exchange—即BX 指令来实现的。指令格式为:

    Thumb状态     BX Rn
    ARM状态       BX<condition> Rn    

      其中Rn可以是寄存器R0—R15中的任意一个。指令可以通过将寄存器Rn的内容拷贝到程序计数器PC来完成在4Gbyte地址空间中的绝对跳转,而状态切换是由寄存器Rn的最低位来指定的,如果操作数寄存器的状态位Bit0=0,则进入ARM状态,如果Bit0=1,则进入Thumb状态。

  • 相关阅读:
    SQL查询语句 group by后, 字符串合并
    正则表达式对象模型
    C#正则表达式编程(四):正则表达式
    C#正则表达式编程(三):Match类和Group类用法
    C#正则表达式编程(二):Regex类用法
    C#正则表达式编程(一):C#中有关正则的类
    正则表达式中-分组构造
    正则表达式-定位点
    正则表达式-字符类减法
    正则表达式-匹配标点符号
  • 原文地址:https://www.cnblogs.com/goodhacker/p/3043158.html
Copyright © 2011-2022 走看看