1.ARM指令集简介

ARM指令集是基于精简指令集计算机(RISC)设计的,其指令集的译码机制相对比较简单,ARMv7-A具有32bit的ARM指令集和16/32bit的Thumb/Thumb-2指令集,ARM指令集的优点是执行效率高但不足之处也很明显,就是代码密度相对低一些。而作为ARM指令集子集的Thumb指令集,代码密度相对比ARM指令高,而且坚持了ARM一贯的性能优但也有一个致命的缺点就是效率低;正所谓鱼和熊掌不可兼得,这也是数字逻辑电路设计所谓的时间和空间的问题;而Thumb-2指令集多为32bit的指令,对于上述的ARM指令和Thumb指令做了一个折中,代码执行效率和密度都相对比较适中。几乎所有的ARM指令都可以条件执行,而另外两者仅有部分才具备此功能,三种指令均可相互调用,而且指令之间状态切换开销很小,几乎可以忽略。

1.1 ARM指令集格式

基本格式: <opcode> {<cond>} {S} <Rd>, <Rn>, {<opcode2>}
< > 尖括号里面的指令助记符是必须的,而{}花括号里面的是可选的。
.opcode:比如MOV,LDR

.cond:即Condition,执行条件,与CPSR的条件标志位对应。

图1 条件码

.S:决定是否影响CPSR的值,见图1
.Rd:目标寄存器
.Rn:第一个操作数的寄存器
.opcode2:第二个操作数,可选,可以是立即数、寄存器、寄存器移位等

1.2 ARM汇编指令分类

包括存储加载类指令集,数据处理类指令集,分支跳转类指令集,程序状态寄存器访问指令以及协处理器类指令集

1>.存储加载类:

由于ARM处理器采用了统一编址技术,因而对外围I/O,程序数据的访问都要通过加载/存储(Load/Store)指令来进行。ARM的加载/存储指令(LDR,STR)是可以实现字,半字,无符号,有符号字节操作;

批量加载/存储(LDM,STM)可以实现一条指令加载存储多个存储器的内容,加载效率大为提高,一般用来传递参数和复制数据,可以说是一般加载/存储的加强版。
LDR:用于从内存中读取数据加载到内存中;比如 LDR R0, [R1]表示将R1所指向的存储单元的内容加到R0寄存器中
STR:将寄存器中的数据保存到内存单元;STR R0, [R1]将R0寄存器里面的数据保存到R1所指向的内存中。
LDM:实现一块连续的内存单元的数据加载多个寄存器中
STM:实现在多个寄存器的数据保存到一块连续的内存单元之中。
格式:LDM/STM  {cond} <mode> Rn{!} {reglist} {^}
.cond:同上

.mode:地址变化模式共8种,常用IA,FD分别表示每次传送数据后地址加4,滿递减堆栈。

图2  地址变换模式

.Rn:基址寄存器,不允许是R15.
.!:感叹号表示是否将最后的地址存入Rn
.Reglist:寄存器列表,按从小到大的顺序排列,当标号连续时可用'-'连接,{R0-R3},不连续时用逗号连接
."^":(假如寄存器列表含有PC寄存器R15)表示指令执行后SPSR的值自动复制给CPSR,常用于从中断处理函数中返回。
反之,默认操作的是用户模式下的寄存器,并非当前特殊模式的寄存器。
试问LDMIA R0, {R1-R4}和LDMIA R0!, {R1-R4}有什么区别?附:在ARM状态下执行32位字对齐的ARM指令;
区别就在于后者将最后的地址赋给了R0!!!!

2>.数据处理类指令集

包括数据传送指令MOV,算术逻辑运算符ADD,SUB,BIC,ORR,比较指令CMP,TST等

.MOV:寄存器与寄存器之间的数据传送,或者立即数传到目标寄存器中。
MOV R0, #8
MOV R0, R1
MOV R0, R1, LSL #3
MOV PC, LR @该指令可以实现子程序的返回,PC和LR由ARM汇编器对ARM寄存器做了预定义。PC即为R15,LR即为R14,也就等于:MOV R15, R14
.ADD,SUB:分别是加减指令
ADD R0, R1, #1
ADDS R0, R1, #1@指令执行后可能会影响CPSR的条件标志位。
BIC R0, R2, #0xF@将R2的后4位置清零。
ORR R0, R0, #oxF@将R0的后4位置1(与“1”做或运算,实现置1功能),结果保存到R0
CMP:指令格式 CMP {cond} Rn opcode2,将Rn的值减opcode2,根据操作结果更新相应CPSR的标志位。以便后面的指令判断是否执行
TST:位测试指令格式:TST {cond} Rn, opcode2将Rn的值与opcode2进行按位与操作,根据结果更新CPSR标志位。
SWP:交换指令: SWP {cond} {B} Rd, Rm, [Rn]:将Rn指向的内容加载到目标寄存器Rd,Rm为源寄存器,将该寄存器的数据存储到Rn指向的地址单元。

3>.分支跳转指令:B,BL

.B:直接跳转到指定地址执行,跳转范围+-32MB,格式:B {codn} label
.BL:带返回地址的跳转,指令自动将下一条指令的地址复制到连接寄存器R14中,然后跳转到指定的地址去执行,执行完后返回到跳转前指令的下一条指令处执行。

4>.程序状态寄存器访问指令

通过MSR和MRS配合使用实现对PSR寄存器的访问,通过读-修改-写操作来实现开关中断,切换处理器模式。
.MRS:读程序状态寄存器指令,将PSR中的内容读入到寄存器中MRS {cond} Rd, PSR
.MSR:写程序状态寄存器指令 MSR {cond} psr_fields #immed_8MSR {cond} psr_fields, Rm。field指位域。只有在特权模式下才能对PSR进行修改,
例如切换到管理模式:MSR CPSR_c #0xD3,将0xD3写入CPSR的低8位,此时M[4:0]=0b10011,进入管理模式。
用读-修改-写操作切换到管理模式
MRS R0, CPSR @读出CPSR的值
BIC R0, R0, #0x1F@清0
ORR R0, R0, #0xD3@修改模式
MSR CPSR_cxsf, R0@将修改后的值保存到CPSR

5>.协处理器访问指令

协处理器CP15包含了16个32bit的寄存器,主要用于存储管理
.MCR:ARM寄存器到协处理器的数据传送指令 MCR {cond} P15, 0, Rd, CRn, CRm, {opcode2}
Rd:源寄存器
CRn:协处理器中的寄存器,目标寄存器,存放第一个操作数其编号为C0,C1....C15
.MRC:协处理器到ARM寄存器的数据传送指令
Rd:目标寄存器
CRn:协处理器中的寄存器,源寄存器,存放第一个操作数其编号为C0,C1....C15
CRm:附加的源寄存器,不需要其他信息时CRm为C0.
opcode2:提供附加信息,若为空时,指定为0即可

2.ARM寻址方式

1>.立即寻址:MOV R1, #3
2>.寄存器寻址:MOV R0, R1
3>.寄存器移位寻址:MOV R1, R0, LSL #3
4>.寄存器间接寻址:LDR R0, [R2];将R2指向地址开始的一个字的内容加载到R0.
5>.基址寻址:LDR R1, [R0, #4]
6>.多寄存寻址:一次传送几个寄存器的值。上面已经写了,这边不再赘述了。
7>.堆栈寻址:STMFD SP!, {R0-R2}以滿递减堆栈进行压栈,LDMFD SP!, {R0-R2},数据出栈,放入R0-R2;(默认是小端操作格式)感叹号表示最后堆栈指令更新。
详细的寻址方式可参考七种寻址方式(立即寻址、寄存器寻址)这一篇文章。

3.ARM伪指令和伪操作

伪指令是汇编程序对源程序汇编期间由汇编程序将其替换成合适的ARM指令或者Thumb指令,最终转换成机器指令,常用的有小范围常数或地址加载伪指令ADR,中范围常数或地址加载伪指令ADRL,大范围常数或地址加载伪指令LDR;而伪操作包括符号定义伪操作、数据定义伪操作,汇编控制伪操作,信息报告伪操作等,所有的伪操作均以.开始。
1>.伪指令
ADR:ADR指令被编译器用一条ADD或者SUB进行替换,在ARM状态下,字对齐时加载范围是-1020~1020,字节或者半字对齐时是-255~255。
ADRL:被编译器用两条条ADD或者SUB进行替换,在ARM状态下,字对齐时加载范围是-256K~256K,字节或者半字对齐时是-64K~264K。
LDR:实现将一个32位常数或地址加载到寄存器。
例:通过LDR伪指令,完成GPIO的配置功能,将0xE0200280赋给R1
LDR R1, =0xE0200280
LDR R0, =0x00001111
STR R0, [R1]
2>.GNU ARM伪操作
.align n 伪操作指示编译器将代码段或者数据段以某种方式对齐。n表示以2的n次方字节对齐。
.byte、 .hword、 .word expression分别是在目标文件中插入一个字节,半字,字的值,若需插入多个值,以','隔开。
.data 告诉编译器下面的语句将被编译到可执行文件的数据段。
.text 告诉编译器下面的语句将被编译到可执行文件的代码段。
.extern .extern告诉编译器当前符号不是在本源文件中定义,在其他源文件中定义,在本源文件中可能用到。
.global symbol 表示声明外部标号,即当前标号是在本源文件中定义,在其他文件中可能被引用。
.end 告诉编译器该文件的语句的结束,汇编程序不需要处理之后的任何内容了。
.equ symbol, expression定义常量,类似于C语言的#define宏定义
.include "filename"文件包含伪操作,指示编译器将文件内容插到当前位置开始的地方。
.marcro 宏定义标志,以.marcro表示开始,以.endm表示定义结束,.exitm表示跳出宏定义。

4.APCS规则

APCS(ARM Process Call Standard)也就是指过程调用规则,定义了一系列规则来保证ARM汇编语言和C程序之间能够协调工作。涉及到的函数参数传递问题,返回值传递以及和函数调用过程中的
寄存器的使用,堆栈的使用等问题。

1>.寄存器使用

APCS中,R0-R3用来传递参数,传递参数给子程序和返回子程序结果;R4-R11保存函数的局部变量(Thumb指令集只能使用R4-R7),R12(IP)也能被用在子程序间传递立即数(ARM状态下);

R13(SP)用来做堆栈指针,保存当前处理器模式的栈顶指针,链接寄存器R14(LR)保存子程序的返回过程。

2>.参数传递规则

当参数个数不超过4个时,可用上述的4个寄存器来传递,否则超过的参数使用栈来传递,对于子程序的返回结果,可用R0-R3来传递。

3>.函数的返回值

若返回值是32位的整数时,一般通过寄存器R0来传递,如果是64位的整数时,用R0和R1来传递。

5.arm-linux-gcc编译器

1>.预处理:将预处理输入文件后缀名为".c",".S",输出为".i"工具:arm-linux-cpp
arm-linux-gcc -E -o *.i  *.c/*.S
2>.编译:完成源代码从高级语言到特定的汇编语言代码的转换工具:ccl
arm-linux-gcc -S -o *.s *c
3>.汇编:将编译得到的".s"文件按照一定的指令集转换成一定格式的机器码工具:arm-linux-as
arm-linux-gcc -c -o *.o  *.c/*s/*.S
4>.链接:将汇编生成的目标文件和系统库的目标文件,库文件组装起来,生成在特定处理器平台运行的可执行文件。工具:arm-linux-ld
arm-linux-gcc -o *.c/*s/*S
除了上面的-E, -S, -c, -o选项外,还有-v,-g,-Wall,-Ox,(x=1,2,3...)等选项

简单ARM指令集介绍相关推荐

  1. 论ARMv7 Thumb-2指令集的性能(含Thumb指令集介绍)【转载】

    [摘要] 主要是介绍ARM CPU中的THUMB-2功能,相对于THUMB的比较THUMB-2指令集的扩展,THUMB-2的新指令带来的好处,新指令对性能和代码密度的改进.    如今的嵌入式系统开发 ...

  2. 嵌入式典型ARM处理器介绍以及分类

    笔者电子信息专业硕士毕业,获得过多次电子设计大赛.大学生智能车.数学建模国奖,现就职于南京某半导体芯片公司,从事硬件研发,电路设计研究.对于学电子的小伙伴,深知入门的不易,特开次博客交流分享经验,共同 ...

  3. ARM V7_VFP,ARM V7_VFPV3 与ARM V7_NEON 介绍

    都出现在ARM v7版本,区别如下: ARM V7_VFP只包含VFPv2 ARM V7_VFPV3里的VFP改进到了v3版本 ARM V7_NEON应该在V3版本上增加了NEON(主要提高媒体和信号 ...

  4. 深入iOS系统底层之指令集介绍

    程序员大咖点击右侧关注,免费进阶高级! 作者:欧阳大哥2013 链接:https://www.jianshu.com/p/54884ce976ca 任何形式的转载都请联系作者获得授权并注明出处. 说到 ...

  5. SIMD补充 指令集架构类型 指令集介绍

    文章目录 SIMD 指令集架构类型 CISC的产生.发展和现状 RISC的产生.发展和现状 IA-64(EPIC)产生.发展和现状 RISC与 IA-64(EPIC)相比 指令集介绍 一.X86 二. ...

  6. 什么是Cortex、ARMv8、arm架构、ARM指令集、soc

    参考:到底什么是Cortex.ARMv8.arm架构.ARM指令集.soc?一文帮你梳理基础概念[科普] 发布时间: 一口Linux 网址:https://blog.csdn.net/daocaoka ...

  7. ARM指令集与Thumb指令集--区别关联--汇编指令 BX LR ; 跳转回LR地址处,既可以是ARM模式也可以是Thumb模式

    BX        LR    ; 跳转回LR地址处,既可以是ARM模式也可以是Thumb模式 A 一.现在先区分下ARM指令集与Thumb指令集        Thumb 指令可以看作是 ARM 指 ...

  8. ARM 指令集跳转指令

    一.跳转指令 跳转指令用于实现程序流程的跳转,在ARM 程序中有两种方法可以实现程序流程的跳转: Ⅰ.使用专门的跳转指令. Ⅱ.直接向程序计数器PC 写入跳转地址值. 通过向程序计数器PC 写入跳转地 ...

  9. 【汇编语言与计算机系统结构笔记01】x86/MIPS/ARM指令集概述与特性,一篇HPCA引发的思考(商业生态的决定性作用)

    资源Bilibili AV46914471 + AV57921488 汇编语言与计算机系统结构 清华大学 张悠慧 本次笔记内容: 01.汇编语言与计算机系统结构 02.汇编基础知识--指令集综述 文章 ...

最新文章

  1. 进程和线程基础知识全家桶,30 张图一套带走
  2. CCF201612-3 权限查询(100分)
  3. Linux_自制系统服务启动脚本
  4. 让PHP更快的提供文件下载
  5. 如何解决数据一致性、任务调度、流水号生成等问题?
  6. Tomcat实现session的代码逻辑分析
  7. Gym - 102001K Boomerangs 构造 + 三元环
  8. RUNOOB python练习题 14
  9. [react] 举例说明useState
  10. centOS安装openoffice的方法
  11. 企业信息化解决方案——插件式平台开发框架
  12. 三年研发、数亿美元成本,Mate 20的“大杀器”麒麟980是怎样炼成的?
  13. iphone个人热点无法开启_iPhone无法开启个人热点怎么回事【解决方法】
  14. 7-2 两个数的简单计算器 (10 分)
  15. JAVA程序员--壁纸
  16. vscode阅读linux源码
  17. QT通过ODBC连接MySQL数据库
  18. 关于右键无法选择codeblocks打开cpp或c文件
  19. vue项目报错[Vue warn]: Property “visible“ must be accessed with “$data.visible“ because properties start
  20. 逆水寒2021最新服务器,《逆水寒》2021上半年大事记:养娃带娃乐趣多,新职业新玩法不断更新...

热门文章

  1. dell服务器磁盘的状态变成foreign
  2. 如何在团队建设工程师文化?阿里资深技术专家这么做
  3. Leaflet L.Polyline.SnakeAnim.js报错《Uncaught Error: Invalid LatLng object: (NaN, NaN)》
  4. Injective Protocol官方文档翻译(十) -预言机(Oracle)
  5. 考一建的难度是不是要比二建大很多?
  6. 腾讯云交通云总经理冯宇彦:基于大数据与人工智能的智慧交通云
  7. mysql cas_CAS SSO一直無法連線到MYSQL
  8. react学习(一)-初始项目
  9. 人眼视觉介绍,像素,分辨率,帧率,码率,清晰度关系
  10. Linux 下 Redis 安装常见问题及解决方案