• ArmV8常用汇编指令2


    接上文,我们来分析一些具体指令。

    1.加载存储指令

    Load/Store可以分为立即数、寄存器等操作,格式如下:

            这里Rn和Rt均为4位,原因在于,A32/T32是16个通用寄存器。因此使用4bit刚好可以遍历所有。如果是运行在AArch64,则需要5bit。

            好,上述格式问题后续再讨论,先看下指令。

            在该架构中,所有数据处理都需要在通用寄存器中完成,首先需要把待处理数据从内存加载到通用寄存器,处理后把结果写入内存。

    常见内存加载指令:

    LDR

    Word load

    LDRD

    Dword load

    LDRB

    Byte load

    LDRH

    Halfword load

    LDRSB

    Signed byte load

    LDRSH

    Signed haflword load

    常见存储指令:

    STR

    Word store

    STRD

    Dword store

    STRB

    Byte store

    STRH

    Halfword store

    在使用load/store指令时,需要了解寻址的方式。具体如下:

    寻址模式

    举例

    基地址寻址

    LDR r0,[r1]

    将r1中的数据加载到r0

    基地址+偏移寻址(前变基)

    LDR r0,[r1,#8]

    将r1+8(必须是8的倍数)的内存数据加载到r0

    后变基

    LDR r0,[r1],#8

    将r1的值加载到r0,然后再加立即数8

    基地址扩展

    LDR r0,[r1,r2]

    R1的值+r2的值,加载到r0

    PC相对地址

    LDR rx,

    lable内存地址赋给rx,必须是PC附近的地址

    LDR\LDRB\LDRSB\LDRH\LDRSH ±4095

    LDRD ±255

            LDR伪指令(大范围内加载地址),格式如下:

            LDR Rt, =

            当该指令第二个参数为=时,表示伪指令,否则就是普通的内存访问指令。

    例如

    1. data:
    2. .long 0x1
    3. LDR R1, = data
    4. LDR R0, [R1]

            首先将数据0x1加载到寄存器R1中(伪指令);

            然后第二条LDR是普通内存访问指令,以R0寄存器的值作为内存地址,加载这个内存地址的值到R0,因此R0值为0x1。

    多字节内存load/store指令

    {}{} Rb{!},

    LDM r10,{r0, r1, r4} 

    2 数据处理指令

    • 运算

    指令

    含义

    举例

    ADD

    不进位加

    ADD r0, r1,r2

    ADC

    带进位加

    SUB

    不进位减

    SUB r0, r1,r2 // r0 = r1-r2

    注意如果要用立即数,只能用T32

    SUB Rd, r1,#1

    SBC

    带进位减

    RSB

    不进位的反减法

    RSB r0, r1,r2 // r0 = r2-r1

    RSC

    带进位的反减法

    CMN

    负数比较,把寄存器和另一个寄存器或者立即数取反后进行比较,更新CPSR条件标志位的值

    CMN r1,#100 //r1的值和100相加,根据结果设置CPSR标志位

    CMP

    比较

    CMP r1, #100  //r1-100,根据结构设置CPSR标志位,不存储结果

    AND

    逻辑与

    BIC

    位清除:用Operand2中相应位的补码对Rn中的位执行与运算

    BIC Rd, Rn,Oprand2

    EOR

    逻辑或

    TST

    用Operand2测试Rn(按位与),不改变Rn,值更新标志位

    TST Rn, Operand2

    TEQ

    用Operand2测试Rn(按位异或),不改变Rn,值更新标志位

    TEQ Rn, Operand2

    MOV

    Copy

    MOV r0,r1 //copy r1 to r0

    • 移位、旋转

            其中,ASR:算数右移,带符号的右移,符号bit位是[32];右移n位,左边被移走的n位用符号bit[31]进行填充

    • 乘除法

    • 位操作

    • 字节反转

    3 控制流指令

    • 分支指令

    B:跳转

    BL:带返回地址(存放到R14)的跳转

    BLX:带指令转换、返回地址的跳转 BLX Rn 当Rnbit0置1时,切到T32;置0,切到A32

    • CBZ/CBNZ

    语法格式:CB(N)Z ,

    CBZ  如果Rn等于0,则跳转到label指向

    CBNZ 如果Rn不等于0,跳转到label

    注意,该指令只能branch 4到130byte

    • IT{T/E}{T/E}{T/E}

    • Supervisor Call(SVC)/Hypervisor Call(HVC)

            语法:SVC #imm。SVC指令导致异常。这意味着处理器模式变为Supervisor,即CPSR保存为Supervisor模式SPSR,并执行分支到SVC向量。Imm被处理器忽略。但是,异常处理程序可以检索它,以确定正在请求什么服务

            HVC #imm 处理器进入Hyp模式,CPSR值保存到Hyp模式SPSR,执行分支到HVC向量。

            HVC不能处于IT块里

    4 Misc指令

    • 协处理器指令

    CDP  初始化一个协处理器数据处理操作

    MRC  将协处理器的值移动到ARM寄存器

    MCR  将ARM寄存器值移动到协处理器

    LDC   从内存中加载到协处理器寄存器

    STC   从协处理器存储到内存

    • PSR访问

    使用MSR 从通用寄存器(或者立即数)传输数据给SPSR/CPSR;

    使用MRS把CPSR/SPSR内容传递给通用寄存器,例如下面这段代码

    MRS r0,CPSR    // read CPSR into r0

    BIC r0,r0,#0x80 //清除IRQ mask,使能IRQ

    MSR CPSR_c, r0   //只修改CPSR_c这一个bit

    SETEND 用于选择数据访问是大端还是小端(用于选择大小端混用系统)

    • BKPT\WFI\NOP等

    BKPT Breakpoint,用于debug代理商

    WFI wait for interrupt ,cpu切至standby、等待debug或者中断时间

    NOP,没有操作

    5 新的A32/T32指令

    6 DSP

    DSP指令都是single instruction multiple data

  • 相关阅读:
    17.3.2.5 灰度(内存处理)
    平衡二叉树的 AVL 实现
    猿创征文|【概率论基础进阶】随机事件和概率-概率及概率公式
    VSCode安装离线插件
    SpringAOP详解,使用SpringAop实现统一日志处理,异常处理
    Linux驱动——platform设备驱动实验
    Java中使用定时器监听数据变化,当满足某个条件时(例如没有数据更新)自动执行某项任务
    lv_table
    关于python 的自动化测试--初学
    FastAPI 学习之路(二)
  • 原文地址:https://blog.csdn.net/djkeyzx/article/details/134434309