常用Arm汇编指令

ARMV7架构下常用汇编指令

简介

​ ARMv7架构是一个32位处理器架构。它也是一种加载/存储体系结构,这意味着数据处理指令只对通用寄存器中的值进行操作。只有加载和存储指令才能访问内存。通用寄存器也是32位的。在本书中,当我们提到一个字时,我们指的是32位。因此双字是64位宽,半字是16位宽。尽管ARMv7体系结构是32位体系结构,但单个处理器实现不一定对所有块和互连都具有32位宽度。例如,可以为指令获取或数据访问提供64位或更宽的路径。大多数ARM处理器支持两种甚至三种不同的指令集,而有些(例如Cortex-M3处理器)实际上并不执行原始的ARM指令集。ARM处理器至少可以使用两种指令集。

​ Arm指令集为32位指令是原始指令集。

​ Thumb指令集最初是在ARM7TDMI处理器中添加的,它只包含16位指令,以牺牲一些性能为代价提供了更小的程序(在较小的嵌入式系统中,内存占用可能是一个主要问题)。最近的处理器,包括Cortex-A系列,都支持Thumb-2技术,该技术扩展了Thumb指令集,以提供16位和32位指令的混合。这提供了两全其美的效果,性能与ARM指令集相似,代码大小与Thumb指令相似。由于Thumb-2的大小和性能优势,编译或组装所有代码以利用Thumb-2技术的做法越来越普遍。

​ ARMV7架构提供16个32位通用寄存器(R0-R15)供软件使用。其中15个(R0-R14)可用于通用数据存储,而R15是程序计数器,其值随着核心执行指令而改变。软件对R15的显式写入将改变程序流程。软件还可以访问CPSR,以及从先前执行模式中保存的CPSR副本,称为已保存的程序状态寄存器(SPSR)。
在这里插入图片描述

1.数据处理指令

​ ARM内核只能在寄存器上执行数据处理,而不能直接在内存上执行。数据处理指令(大多数情况下)使用一个目标寄存器和两个源操作数。基本格式可以认为是操作码,可选地后跟条件码,可选地后跟S(设置标志),如下所示

操作码{可选条件}-S(设置标志) (Rd目标寄存器) 操作数1(Rn)  操作数2(OP)

1.1算数运算

  • ADC 进位加
/*格式:*/ADC Rd,Rn,OP2  /*Rd = Rn + Op2 + C*/
ADC r0,r1,#0x2 
/*如果r1的值为0x2,那么r0的值就为r1+0x2+1也就是0x2+0x2+0x1=5*/
  • ADD 加法
/*格式:*/ADD Rd, Rn, Op2  /*Rd = Rn + Op2*/
ADD r0,r1,#0x3
/*r0 = r1+3*/
  • MOV 赋值(转移)
/*格式:*/MOV Rd, Op2  /* Rd = Op2*/
MOV r0,#0x3
/*r0 = 0x3*/
movl
mov long : 传送字长 : 32位;把32位立即数放到寄存器

movw
mov word:传送字 :16位; 把 16 位立即数放到寄存器的底16位,高16位清0

movb
mov byte:传送字节 :8位;把8位立即数放到寄存器

movs
s(s标志)功能不变,影响CPSR标志位
movs r0, #0 默认结果为零但不影响CPSR的Z位,加上s以后会影响CPSR标志位
  • MVN (取非赋值)
/*格式:*/MVN Rd, Op2 /*  Rd = ~Op2*/
MVN r0,#0x3
/*r0 = ~0x3*/
  • RSB (反向相减)
/*格式:*/RSB Rd, Rn, Op2 /*  Rd = Op2 – Rn*/
rsb r0,r1,#0x3
/*r0 = 0x3-r1*/
  • RSC (反向相减携带)
/*格式:*/RSC Rd, Rn, Op2 /*  Rd = Op2 – Rn - !C*/
rsc r0,r1,#0x3
/*r0 = 0x3-r1 -0*/
  • SBC (相减携带)
/*格式:*/SBC Rd, Rn, Op2 /*  Rd =Rn-Op2 - !C*/
sbc r0,r1,#0x3
/*r0 =r1- 0x3-0*/
  • SUB(相减)
/*格式:*/SUB Rd, Rn, Op2 /*  Rd = Rn – Op2*/
sub r0,r1,#0x3
/*r0 = r1-0x3*/
  • 乘法运算
指令格式含义实例
MLSRd, Rn, Rm, Ra乘法与减法结合Rd = Ra - (Rm × Rn)
MLARd, Rn, Rm, Ra乘法与加法结合Rd = Ra + (Rn × Rm)
MULRd, Rn, Rm乘法Rd = Rn × Rm
SMLALRdLo, RdHi, Rn, Rm32位符号数乘以一个64位数RdHiLo += Rn × Rm
SMULLRdLo, RdHi, Rn, Rm有符号64位数相乘RdHiLo = Rn × Rm
UMLALRdLo, RdHi, Rn, Rm无符号64位数累计和RdHiLo += Rn × Rm
UMULLRdLo, RdHi, Rn, Rm无符号64位乘法RdHiLo = Rn × Rm

1.2逻辑运算与标志指令

  • AND(与运算)
/*格式:*/AND Rd, Rn, Op2/*  Rd = Rn & Op2*/
and r0,r1,#0x3
/*r0 = r1&0x3*/
  • BTC(位清除)
/*格式:*/BIC Rd, Rn, Op2/*  Rd = Rn & ~ Op2*/
bic r0,r1,#(0x1 << 12)
/*将r1寄存器第12位清零并赋值给r0寄存器*/
  • EOR(异或)
/*格式:*/EOR Rd, Rn, Op2/*  Rd = Rn ^ Op2*/
eor r0,r1,#0x1
/*r0 = r1^1*/
  • ORR(或运算)

    /*格式:*/ORR Rd, Rn, Op2/*  Rd = Rn | Op2*/
    orr r0,r1,#0x1
    /*r0 = r1|1*/
    

    ARMV7架构(CPSR)程序当前状态寄存器如下所示
    在这里插入图片描述

    • N 表示运算结果为假

    • Z 表示运算结果为0

    • C 表示运算结果进位

    • V 表示运算结果溢出

    • CMP (比较)

    /*格式:*/CMP Rn, Op2/*  Rn – Op2*/
    CMP r0,r1
    /*r0-r1*/
    
    CMP结果ZFCF
    目的操作数 < 源操作数01
    目的操作数 > 源操作数00
    目的操作数 = 源操作数10

    上为无符号数比较

    下为有符号比较

    CMP结果标志位
    目的操作数 < 源操作数SF ≠ OF
    目的操作数 > 源操作数SF = OF
    目的操作数 = 源操作数ZF = 1
    • CMN(比较取负的值)
    /*格式:*/CMN Rn, Op2/*  Rn + Op2*/
    CMP r0,r1
    /*r0+r1*/
    
    • TEQ(测试等价)
    /*格式:*/TEQ Rn, Op2/*  Rn ^ Op2*/
    teq r0,r1
    /*r0^r1*/
    
    • TST(测试)
    /*格式:*/TST Rn, Op2/*  Rn & Op2*/
    tst r0,r1
    /*r0&r1*/
    

1.3 操作数2的灵活性

add r0,r1,#1  /*r0=r1+1*/
add r0,r1,r2	/*r0=r1+r2*/
add r0,r1,r2,LSL #4 /*r0=r1+r2<<4*/
add r0,r1,r2,LSL r3 /*r0=r1+r2<<r3*/

2.内存访问

2.1 LDR指令

​ LDR (Load Register)将一个值从内存加载到ARM寄存器,可以选择更新用于给出地址的寄存器。

格式如下

LDR{type}{T}{cond} Rt, [Rn {, #offset}] 

LDR{type}{cond} Rt, [Rn, #offset]! 

LDR{type}{T}{cond} Rt, [Rn], #offset 

LDR{type}{cond} Rt, [Rn, +/-Rm {, shift}] 

LDR{type}{cond} Rt, [Rn, +/-Rm {, shift}]! 

LDR{type}{T}{cond} Rt, [Rn], +/-Rm {, shift} 

type字段可以为

• B – 无符号数(32位)
• SB – 有符号数(32位)
• H – 无符号数半字节(32位数高16或低16)
• SH – 有符号数半字节. (32位数高16或低16)

寻址方式实例

(1) LDR R0, [R1] 加载R1指向的地址到R0
(2) LDR R0, [R1, R2] 加载R1+R2指向的地址到R0
(3) LDR R0, [R1, R2, LSL #2] 加载R1+(R2<<2)指向的地址到R0
(4) LDR R0, [R1, #32]! 加载 R1+32 指向的地址然后 R1:=R1 + 32 
(5) LDR R0, [R1], #32 从R1所指向的地址读取R0 然后R1:=R1 + 32

3.流控制

3.1 B

直接跳转不返回,对于简单的相对分支(相对于当前地址的偏移量),使用B指令。

3.2 BL

跳转并返回到连接地址,一般用于函数调用。调用子程序时,如果返回,地址必须存储在链接寄存器中,则使用BL指令

3.3BLX与BX

如果你想改变指令集(从ARM到Thumb或Thumb到ARM),使用BX或BLX。

4.系统(协处理器、调试、模式更改等)

协处理器协处理器指令占用部分ARM指令集。最多可实现16个协处理器,编号为0到15 (CP0, CP1…CP15)

  • Coprocessor 15是一个内置的协处理器,提供对许多核心功能的控制,包括缓存和MMU。
  • Coprocessor14是一个内置的协处理器,它控制核心的硬件调试设施,比如断点单元。
  • 协处理器10和11可以访问系统中的浮点和NEON硬件。
tips
如果执行了协处理器指令,但是系统中没有相应的协处理器,则会发生未定义指令异常.

协处理器指令有五类

  • CDP 启动协处理器数据处理操作。
  • MRC 从协处理器寄存器移到ARM寄存器。
  • MCR -从ARM寄存器移到协处理器寄存器
  • LDC 从内存加载协处理器寄存器
  • STC 从协处理器寄存器存储到存储器。
tips
我们操作一些特殊寄存器时例如CPSR寄存器时我们一般使用MRC将CPSR读取到arm寄存器,操作完后用MCR写回到
CPSR寄存器。

5.其他

简单介绍几个ARM架构下的主要寄存器

堆栈指针R13(SP)
每一种异常模式都有其自己独立的r13,它通常指向异常模式所专用的堆栈,当ARM进入异常模式的时候,程序就可以把一般通用寄存器压入堆栈,返回时再出栈,保证了各种模式下程序的状态的完整性。
连接寄存器R14(LR)
保存子程序返回地址。使用BL或BLX时,跳转指令自动把返回地址放入r14中;
子程序通过把r14复制到PC来实现返回,通常用下列指令:MOV PC, LR;BX LR;
当异常发生时,异常模式的R14用来保存异常返回地址,将R14如栈可以处理嵌套中断。
程序计数器R15(PC)

​ 保存当前程序执行指令的首地址。

  • PUSH(入栈)

主要用于保存一些临时的变量用于调用。

  • POP(出栈)

主要用于读取入栈的变量的值。

  • CPS

​ 主要用于在特权模式下直接修改CPSR寄存器的值,不需要使用MRC和MCR指令操作。

  • STR

​ 主要用于把源寄存器的值放到存储器中去。指令格式可以参考LDR指令

GNU汇编与arm区别
在这里插入图片描述

通常用下列指令:MOV PC, LR;BX LR;
当异常发生时,异常模式的R14(LR链接寄存器)用来保存异常返回地址(PC),将R14如栈可以处理嵌套中断。
程序计数器R15(PC)

​ 保存当前程序执行指令的首地址。

  • PUSH(入栈)

主要用于保存一些临时的变量用于调用。

  • POP(出栈)

主要用于读取入栈的变量的值。

  • CPS

​ 主要用于在特权模式下直接修改CPSR寄存器的值,不需要使用MRC和MCR指令操作。

  • STR

​ 主要用于把源寄存器的值放到存储器中去。指令格式可以参考LDR指令

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ARM指令集是一种广泛使用的指令集架构,它主要用于移动设备、嵌入式系统和低功耗服务器等领域。这个指令集架构的发展可追溯到1980年代初,但只有1990年代后期开始得到广泛采用和推广。现在,ARM指令集已经成为了全球最流行的指令集之一。 常用ARM指令集包括ARMv6、ARMv7和ARMv8等。它们的主要区别在于处理器的架构和指令集的扩展。其中,ARMv6是一种比较老的架构,适用于早期的移动设备和嵌入式系统。而ARMv7则是一种更为先进的架构,支持更多的指令集扩展和一些新的特性。ARMv8则是未来的趋势,它支持更多的指令集扩展,包括虚拟寄存器、硬件虚拟化和安全性增强等功能。 除了ARM指令集,汇编语言也是ARM编程的重要组成部分。常用ARM汇编语言包括ARM汇编Thumb汇编两种。ARM汇编是一种较为底层的汇编语言,它使用32位指令来完成数据处理和控制流操作。而Thumb汇编则是一种更加轻量级的汇编语言,它使用16位指令来完成相同的操作。 针对ARM指令集和汇编语言,有许多文档和教程可供参考。其中最常用的包括ARM体系结构参考手册、ARM汇编编程指南和ARM编程手册等。这些文档都提供了详细的指令集和汇编语言说明,以及实用的编程示例和技巧。同时,还有一些在线资源和社区,如ARM开发者中心和ARM社区等,提供丰富的资讯和交流平台。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值