ARM-汇编指令集(总结)

2019-12-03来源: eefocus关键字:ARM  汇编  指令集

ARM汇编指令集

指令、伪指令

(汇编)指令:   是机器码的助记符,经过汇编器编译后,由CPU执行。 

(汇编)伪指令:用来指导指令执行,是汇编器的产物,最终不会生成机器码。


有两种不同风格的ARM指令

1).ARM官方的ARM汇编风格:指令一般用大写,Windows中的IDE开发环境。

2).GNU风格的ARM汇编:指令一般用小写。


ARM汇编的特点

1. LDR/STR架构

1).ARM采用RISC架构,CPU本身不能直接读取内存,而需要先将内存中内容加载入CPU中通用寄存器中才能被CPU处理。
2).ldr(load register)指令将内存内容加载入通用寄存器。
3).str(store register)指令将寄存器内容存入内存空间中。
4).ldr/str组合用来实现 ARM CPU和内存数据交换。

2. 至此8种寻址方式

1).寄存器寻址mov r1, r2。
2).立即(立即数)寻址 mov r0, #0xFF00。
3).寄存器移位寻址 mov r0, r1, lsl #3。
4).寄存器间接寻址 ldr r1, [r2] 表示内存,内存地址存在r2这个寄存器中,把内存地址里的值给r1。

5).基址变址寻址ldr r1, [r2, #4]内存地址在r2+4里面。

6).多寄存器寻址 ldmia r1!, {r2-r7, r12}一次访问多个寄存器。
7).堆栈寻址 stmfd sp!, {r2-r7, lr}。
8).相对寻址      beq flag。

3. 指令后缀

同一指令经常附带不同后缀,变成不同的指令。经常使用的后缀有:
B(byte)功能不变,操作长度变为8位
H(half word)功能不变,长度变为16位
S(signed)功能不变,操作数变为有符号
如 ldr ldrb ldrh ldrsb ldrsh
S(S标志)功能不变,影响CPSR标志位
如 mov和movs movs r0, #0

4. 条件执行后缀

条件后缀是否成立取决于当前代码的前面的代码。

条件后缀只影响当前代码的执行。

5. 多级指令流水线

为增加处理器指令流的速度,ARM使用多级流水线.,下图为3级流水线工作原理示意图。(S5PV210使用13级流水线,ARM11为8级)
允许多个操作同时处理,而非顺序执行。

1).PC指向正被取指的指令,而非正在执行的指令


数据传输与跳转指令详解

1. 数据处理指令

数据传输指令 mov mvn
算术指令 add sub rsb adc sbc rsc 
逻辑指令 and orr eor bic
比较指令 cmp cmn tst teq
乘法指令 mvl mla umull umlal smull smlal
前导零计数 clz


2. cpsr访问指令

mrs & msr
mrs用来读psr,msr用来写psr
CPSR寄存器比较特殊,需要专门的指令访问,这就是mrs和msr。

3. 跳转(分支)指令

b & bl & bx
b 直接跳转(就没打开算返回)
bl branch and link,跳转前把返回地址放入lr中,以便返回,以便用于函数调用
bx跳转同时切换到ARM模式,一般用于异常处理的跳转。

4. 访存指令

ldr/str & ldm/stm & swp
单个字/半字/字节访问 ldr/str
多字批量访问  ldm/stm
swp r1, r2, [r0]
swp r1, r1, [r0]

5. 软中断指令

swi(software interrupt)
软中断指令用来实现OS中系统调用

ARM汇编中的立即数

合法立即数与非法立即数
ARM指令都是32位,除了指令标记和操作标记外,本身只能附带很少位数的立即数。因此立即数有合法和非法之分。
合法立即数:经过任意位数的移位后非零部分可以用8位表示的即为合法立即数。


协处理器与协处理器指令集

6.协处理器cp15操作指令

mcr & mrc
mrc用于读取CP15中的寄存器
mcr用于写入CP15中的寄存器

7.arm寻址方式

1). 寄存器:    MOV R1,R2 ; R2->R1

2). 立即数:    SUBS R0,R1,#1; R0=R1-1

3). 寄存器移位:MOV R0,R2,LSL #3 ;R2左移三位->R0 

4). 间接寻址:  LDR R1,[R2] ; 装载R2指向的内存数值至R1

5). 基址寻址:  LDR R2,[R3,#0x0F] ;R3+0x0F作为地址,将所

 

指向的置装入R2.R3的值不改变

6). 多寄存器寻址: LDMIA R1!,{R2-R7,R12} ; 将R1所指向的内

 

存块依次装入{}中的寄存器。

STMIA R0!,{R3-R6,R10} ;将{}列出的寄存器里的值依次填入R0所指向的内存块。

7). 相对寻址: BL XXX ;跳转 

BEQ XXX ;条件跳转

协处理器解析:

SoC内部另一处理核心,协助主CPU实现某些功能,被主CPU调用执行一定任务。
ARM设计上支持多达16个协处理器,但是一般SoC只实现其中的CP15.(cp:coprocessor)
协处理器和MMU、cache、TLB等处理有关,功能上和操作系统的虚拟地址映射、cache管理等有关。


MRC & MCR的使用方法

mcr{}   p15, , , , , {}
opcode_1:对于cp15永远为0
Rd:ARM的普通寄存器
Crn:cp15的寄存器,合法值是c0~c15
Crm:cp15的寄存器,一般均设为c0
opcode_2:一般省略或为。

 

ldm/stm与栈的处理

为什么需要多寄存器访问指令

ldr/str每周期只能访问4字节内存,如果需要批量读取、写入内存时太慢,解决方案是stm/ldm
ldm(load register mutiple)
stm(store register mutiple)

举例(uboot start.S 537行)

stmia sp, {r0 - r12}
将r0存入sp指向的内存处(假设为0x30001000);然后地址+4(即指向0x30001004),将r1存入该地址;然后地址再+4(指向0x30001008),将r2存入该地址······直到r12内容放入(0x3001030),指令完成。
一个访存周期同时完成13个寄存器的读写


后缀的种类:

ia(increase after)先传输,再地址+4
ib(increase before)先地址+4,再传输
da(decrease after)先传输,再地址-4
db(decrease before)先地址-4,再传输
fd(full decrease)满递减堆栈
ed(empty decrease)空递减堆栈
fa(·······) 满递增堆栈
ea(·······)空递增堆栈


四种栈解析:

空栈:栈指针指向空位,每次存入时可以直接存入然后栈指针移动一格;而取出时需要先移动一格才能取出。
满栈:栈指针指向栈中最后一格数据,每次存入时需要先移动栈指针一格再存入;取出时可以直接取出,然后再移动栈指针。
增栈:栈指针移动时向地址增加的方向移动的栈。
减栈:栈指针移动时向地址减小的方向移动的栈。


!的作用:

ldmia r0, {r2 - r3}
ldmia r0!, {r2 - r3}

感叹号的作用就是r0的值在ldm过程中发生的增加或者减少最后写回到r0去,也就是说ldm时会改变r0的值。


^的作用:

ldmfd sp!, {r0 - r6, pc}
ldmfd sp!, {r0 - r6, pc}^


^的作用:在目标寄存器中有pc时,会同时将spsr写入到cpsr,一般用于从异常模式返回。


总结:批量读取或写入内存时要用ldm/stm指令。
各种后缀以理解为主,不需记忆,最常见的是stmia和stmfd。
谨记:操作栈时使用相同的后缀就不会出错,不管是满栈还是空栈、增栈还是减栈。

 

常用gun伪指令:

global _start @ 给_start外部链接属性
.section .text @ 指定当前段为代码段
.ascii .byte .short .long .word 
.quad .float .string @ 定义数据
.align 4 @ 以4字节对齐
.balignl 16 0xabcdefgh @ 16字节对齐填充
.equ @ 类似于C中宏定义


偶尔会用到的gun伪指令

.end @标识文件结束
.include @ 头文件包含
.arm / .code32 @声明以下为arm指令
.thumb / .code16 @声明以下为thubm指令

重要的几个伪指令

ldr 大范围的地址加载指令
adr 小范围的地址加载指令
adrl 中等范围的地址加载指令
nop 空操作
ARM中有一个ldr指令,还有一个ldr伪指令
一般都使用ldr伪指令而不用ldr指令

adr与ldr

adr编译时会被1条sub或add指令替代,而ldr编译时会被一条mov指令替代或者文字池方式处理;
adr总是以PC为基准来表示地址,因此指令本身和运行地址有关,可以用来检测程序当前的运行地址在哪里
ldr加载的地址和链接时给定的地址有关,由链接脚本决定。

关键字:ARM  汇编  指令集 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic481821.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:关于ARM的内核架构
下一篇:nandflash的读写(2440)

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

ARM的启动分析
基于ARM的芯片多数为复杂的片上系统,这种复杂系统里的多数硬件模块都是可配置的,需要由软件来设置其需要的工作状态。因此在用户的应用程序之前,需要由专门的一段代码来完成对系统的初始化。由于这类代码直接面对处理器内核和硬件控制器进行编程,一般都是用汇编语言。一般通用的内容包括:中断向量表初始化存储器系统初始化堆栈初始化有特殊要求的断口,设备初始化用户程序执行环境改变处理器模式呼叫主应用程序 1. 中断向量表ARM要求中断向量表必须放置在从0地址开始,连续8X4字节的空间内。每当一个中断发生以后,ARM处理器便强制把PC指针置为向量表中对应中断类型的地址值。因为每个中断只占据向量表中1个字的存储空间,只能放置一条ARM指令,使
发表于 2019-12-05
ARM的启动分析
arm交叉编译器gnueabi、none-eabi、arm-eabi、gnueabihf的区别
命名规则交叉编译工具链的命名规则为:arch [-vendor] [-os] [-(gnu)eabi] [-gcc]arch – 体系架构,如ARM,MIPSvendor – 工具链提供商os – 目标操作系统eabi – 嵌入式应用二进制接口(Embedded Application Binary Interface)注意没有vendor时,用none代替;没有os支持时,也用none代替同进没有vendor和os支持时,只用一个none代替,比如arm-none-eabi中的none表示既没有vendor也没有os支持。根据对操作系统的支持与否,ARM GCC可分为支持和不支持
发表于 2019-12-04
arm交叉编译器gnueabi、none-eabi、arm-eabi、gnueabihf的区别
浅析ARM汇编语言子例程设计方法
引言在嵌入式软件系统开发过程中,大量使用C语言进行应用程序开发以提高开发效率。同时,系统中经常包含一些决定整个系统性能的关键模块,此时为了获得最佳性能,经常使用汇编语言编写它们,或者某些特殊情况下,例如操作硬件等,也必须使用汇编语言。函数是C语言中一个重要的概念,在汇编语言中经常使用子例程或过程(subroutine or procedure)表达同样的概念,本文使用术语子例程。本文首先介绍ARM汇编语言子例程设计的一般方法,并以此为基础提出一种新的基于堆栈帧的设计方法,同时介绍与C语言交互技术。1 一般方法在ARM汇编语言中一般使用BL(Branch and Link)指令调用某个子例程,BL指令首先将返回地址保存
发表于 2019-12-04
浅析ARM汇编语言子例程设计方法
iOS逆向工程之Hopper中的ARM指令
一、Hopper中的ARM指令ARM处理器就不多说了,ARM处理器因为低功耗等原因,所以大部分移动设备上用的基本上都是ARM架构的处理器。当然作为移动设备的Android手机,iPhone也是用的ARM架构的处理器。如果你想对iOS系统以及你的应用进一步的了解,那么对ARM指令集的了解是必不可少的,ARM指令集应该也算得上是iOS逆向工程的基础了。当你使用Hopper进行反编译时,里边全是ARM的指令,那是看的一个爽呢。下面就是使用Hopper打开MobileNote.app的一个Hopper的界面。从主窗口中可以看到全是ARM的指令呢,如果你对ARM指令不了解,那么如何进行分析呢,对吧。所以对ARM指令的了解,是iOS逆向工程
发表于 2019-12-04
iOS逆向工程之Hopper中的ARM指令
ARM的栈指令
ARM的栈指令ARM的指令系统中关于栈指令的内容比较容易引起迷惑,这是因为准确描述一个栈的特点需要两个参数:栈地址的增长方向:ARM将向高地址增长的栈称为递增栈(Descendent Stack),将向低地址增长的栈称为递减栈(Acendant Stack)栈指针的指向位置:ARM将栈指针指向栈顶元素位置的栈称为满栈(Full Stack),讲栈指针指向即将入栈的元素位置的栈称为空栈(Empty Stack)1. 栈类型根据栈地址增长方向雨栈指针指向位置的不同,自然可以将栈分为四类:递增栈递减栈空栈EA栈ED栈满栈FA栈FD栈图1描述了四种不同类型的栈,其中虚线部分表示即将入栈的元素。图1 栈类型2. 栈指令栈的操作指令无非两种
发表于 2019-12-04
ARM的栈指令
ARM(RISC)和x86(CISC)的技术差异
RISC和CISC,这一对冤家,从诞生之日开始就处在不停的纠缠之中。直到今天,两者经过多年的发展后,都在各自领域打开了一片天地,并且相互渗透。RISC专注高性能、高性能功耗比、小体积以及移动设备领域,CISC专注桌面、高性能和民用市场。现在,RISC的代表是ARM,而CISC的代表则是我们耳熟能详的x86。那么,他们的技术差异在哪里?究竟是怎样的技术分歧带来了两者如此大的差别呢?指令集的出现要说清楚RISC和CISC,也就是今天热门的ARM和x86之间的差异,还得把时间往前推一些,观察计算机诞生之初的一些事情,才能很清楚地了解指令集、精简和复杂之间的关系。 机器语言的实例机器语言含义
发表于 2019-12-04
ARM(RISC)和x86(CISC)的技术差异
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved