文章目录

  • 1 前言
  • 2 ARM知识图谱
  • 3 ARM汇编基础三大块
    • 3.1 寻址方式
      • 3.1.1 立即寻址
      • 3.1.2 寄存器寻址
      • 3.1.3 寄存器偏移寻址
      • 3.1.4 寄存器间接寻址
      • 3.1.5 基址寻址
      • 3.1.6 多寄存器寻址
      • 3.1.7 堆栈寻址
      • 3.1.8 块拷贝寻址
      • 3.1.9 相对寻址
    • 3.2 寄存器的用途
      • 3.2.1 ARM寄存器列表
      • 3.2.2 ARM寄存器的用途
        • 3.2.2.1 R0~R7
        • 3.2.2.2 R8~R12
        • 3.2.2.3 R13(SP)和R14(LR)
        • 3.2.2.4 程序计数器PC(R15)
        • 3.2.2.5 CPSR和SPSR
    • 3.3 汇编指令
      • 3.3.1 数据处理指令
      • 3.3.2 cpsr访问指令
      • 3.3.3 跳转(分支)指令
      • 3.3.4 访存指令
      • 3.3.5 软中断指令
      • 3.3.6 其他
  • 4 更多分享
  • 5 参考链接

1 前言

玩嵌入式的,或多或少都接触ARM。

ARM既是一种处理器架构,也是一家公司,它不生产芯片,只靠芯片IP授权赚钱。

ARM处理器是英国Acorn有限公司设计的低功耗成本的第一款RISC微处理器。全称为Advanced RISC Machine。ARM处理器本身是32位设计,但也配备16位指令集,一般来讲比等价32位代码节省达35%,却能保留32位系统的所有优势。

更多详细介绍,请参考百度百科.

2 ARM知识图谱

本文先列个大纲,后续有时间再补充。

3 ARM汇编基础三大块

这里整理了ARM汇编中非常基础的三大块知识,了解了这三大块内容基本可以看懂甚至编译一些简单的汇编程序。

3.1 寻址方式

ARM的寻址方式总共有9种,包括:

3.1.1 立即寻址

操作数是立即数,以“#”为前缀,表示 16 进制数值时以“0x”表示。

例:

MOV R0,#0xFF00 ;0xFF00 -> R0

SUBS R0,R0,#1 ;R0 – 1 -> R0

3.1.2 寄存器寻址

操作数的值在寄存器中,指令执行时直接取出寄存器值操作。

例:

MOV R1,R2 ;R2 -> R1

SUB R0,R1,R2 ;R1 - R2 -> R0

3.1.3 寄存器偏移寻址

当第二操作数是寄存器偏移方式时,第二个寄存器操作数在与第一个操作数结合之前,选择进行移位操作。

例:

MOV R0,R2,LSL #3 ;R2 的值左移 3 位,结果放入 R0,即 R0 = R2 * 8

ANDS R1,R1,R2,LSL #3 ;R2 的值左移 3 位,然后和 R1 相与操作,结果放入 R1

可采用的移位操作:

LSL:逻辑左移(Logical Shift Left),低端空出位补 0

LSR:逻辑右移(Logical Shift Right),高端空出位补 0

ASR:算术右移(Arithmetic Shift Right),移位过程中符号位不变,即源操作数为正数,则高端空出位补 0,否则补 1

ROR:循环右移(Rotate Right),由低端移出位填入高端空出位

RRX:带扩展的循环右移(Rotate Right eXtended by 1 place),操作数右移一位,高端空出位用原 C 标志值填充。

3.1.4 寄存器间接寻址

操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针。

例:

LDR R1,[R2] ;将 R2 中的数值作为地址,取出此地址中的数据保存在 R1 中

SWP R1,R1,[R2] ;将R2中的数值作为地址,取出此地址中的数值与 R1 中的值**

3.1.5 基址寻址

将基址寄存器的值与偏移量相加,形成操作数的有效地址,基址寻址用于访问基址附近的存储单元,常用于查表、数组操作、功能寄存器访问等。

例:

LDR R2,[R3,#0x0F] ;将R3中的数值加 0x0F 作为地址,取此地址的值保存在 R2 中

STR R1,[R0,#-2] ;将R0中的数值减 2 作为地址,把 R1的值保存到此地址中

3.1.6 多寄存器寻址

一次传送多个寄存器值,允许一条指令传送 16 个寄存器的任何子集或所有寄存器。多寄存器寻址时,寄存器子集按由小到大的顺序排列,连续的寄存器可用“-”连接,否则,用“,”分隔书写。

例:

LDMIA R1!,{R2-R7,R12} ;将 R1的值读出到 R2-R7,R12,过程中R1 自动加 1

STMIA R0!,{R3-R6,R10};将 R3-R6,R10的值保存到 R0 指向的地址,过程中R0 自动加 1

3.1.7 堆栈寻址

堆栈寻址使用堆栈指针SP,即R13,指向堆栈的栈顶。堆栈可分为两种:

向上生长:向高地址方向生长,称为递增堆栈,

向下生长:向低地址方向生长,称为递减堆栈,

堆栈指针指向最后压入的有效数据项,称为满堆栈,

堆栈指针指向下一个要放入的空位置,称为空堆栈,这样就有 4 种类型的堆栈。

A)满递增:堆栈地址向上增长,堆栈指针指向有效数据的最高地址。如 LDMFA,STMFA。

B)空递增:堆栈地址向上增长,堆栈指针指向堆栈上的第一个空位置。如 LDMEA,STMEA 。

C)满递减:堆栈地址向下增长,堆栈指针指向有效数据项的最低地址。如 LDMFD,STMFD。

D)空递减:堆栈地址向下增长,堆栈指针指向堆栈下的第一个空位置。如 LDMED,STMED 。

例:

STMFD SP!,{R1-R7,LR} ; 将 R1~R7,LR 入栈。满递减堆栈。

LDMFD SP!,{R1-R7,LR} ;数据出栈,放入 R1~R7,LR 寄存器。满递减堆栈。

3.1.8 块拷贝寻址

用于将一块数据从存储器的某一位置拷贝到另一位置。

例:

STMIA R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之后增加,增长方向为向上增长。

STMIB R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之前增加,增长方向为向上增长。

STMDA R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之后增加,增长方向为向下增长。

STMDB R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之前增加,增长方向为向下增长。

3.1.9 相对寻址

相对寻址是基址寻址的一种变通,由程序计数器 PC 提供基准地址,指令中的地址

码字段作为偏移量,两者相加后得到有效地址。

例:

BL ROUTE1 ;调用ROUTE1 子程序

BEQ LOOP ;条件跳转到 LOOP 标号处

LOOP MOV R2,#2

ROUTE1

3.2 寄存器的用途

3.2.1 ARM寄存器列表

ARM共有37个32位物理寄存器,7种工作模式下可访问的寄存器见下表,User和System使用完全相同的物理寄存器。

3.2.2 ARM寄存器的用途

其中 r0~r3 主要用于子程序间传递参数, r4~r11 主要用于保存局部变量,但在 Thumb 程序中,通常只能使用 r4~r7 来保存局部变量; r12 用作子程序间scratch 寄存器,即 ip 寄存器; r13 通常用做栈指针,即 sp; r14 寄存器又被称为连接寄存器(lr),用于保存子程序以及中断的返回地址; r15 用作程序计数器(pc),由于 ARM 采用了流水线机制,当正确读取了 PC 的值后,该值为当前指令地址加 8 个字节,即 PC 指向当前指令的下两条指令地址。

CPSR和SPSR都是程序状态寄存器,其中SPSR是用来保存中断前的CPSR中的值,以便在中断返回之后恢复处理器程序状态。

3.2.2.1 R0~R7

所有工作模式下,R0-R7都分别指向同一个物理寄存器(共8个物理寄存器),它们未被系统用作特殊的用途。在中断或异常处理进行工作模式转换时,由于不同工作模式均使用相同的物理寄存器,可能造成寄存器中数据的破坏。

3.2.2.2 R8~R12

在User&System、IRQ、Svc、Abt和Und模式下访问的R8R12都是同一个物理寄存器(共5个物理寄存器);在FIQ模式下,访问的R8_fiqR12_fiq是另外独立的物理寄存器(共5个物理寄存器)。

3.2.2.3 R13(SP)和R14(LR)

​ 在User&System、IRQ、FIQ、Svc、Abt和Und访问的R13_~R14都是各自模式下独立的物理寄存器(共12个物理寄存器)。

​ R13在ARM指令中常用作堆栈指针(SP),但这只是一种习惯用法,用户也可使用其他的寄存器作为堆栈指针。而在Thumb指令集中,某些指令强制性的要求使用R13作为堆栈指针。

​ 由于处理器的每种工作模式均有自己独立的物理寄存器R13,在用户应用程序的初始化部分,一般都要初始化每种模式下的R13,使其指向该工作模式的栈空间。这样,当程序进入异常模式时,可以将需要保护的寄存器放入R13所指向的堆栈,而当程序从异常模式返回时,则从对应的堆栈中恢复,采用这种方式可以保证异常发生后程序的正常执行。
R14称为链接寄存器(Link Register),当执行子程序调用指令(BL)时,R14可得到R15(程序计数器PC)的备份。在每一种工作模式下,都可用R14保存子程序的返回地址,当用BL或BLX指令调用子程序时,将PC的当前值复制给R14,执行完子程序后,又将R14的值复制回PC,即可完成子程序的调用返回。以上的描述可用指令完成。

执行以下任意一条指令:
MOV PC, LR
BX LR
在子程序入口处使用以下指令将R14存入堆栈:
STMFD SP!,{,LR}
对应的,使用以下指令可以完成子程序返回:
LDMFD SP!,{,PC}
R14也可作为通用寄存器。

3.2.2.4 程序计数器PC(R15)

所有工作模式下访问的R15都是同一个物理寄存器,由于ARM体系结构采用了多级流水线技术,对于ARM指令集而言,PC总是指向当前指令的下两条指令的地址,即PC的值为当前指令的地址值加8个字节。

在ARM状态下,R15[1:0]为0,R15[31:2]用于保存PC;在Thumb状态下,R15[0]为0,R15[31:1]用于保存PC。

3.2.2.5 CPSR和SPSR

R16用作CPSR(Current Program Status Register,当前程序状态寄存器),CPSR可在任何工作模式下被访问,它包括条件标志位、中断禁止位、当前处理器模式标志位,以及其他一些相关的控制和状态位。

每一种工作模式下又都有一个专用的物理状态寄存器,称为SPSR(Specified Program Status Register,备份的程序状态寄存器),当异常发生时,SPSR用于保存CPSR的当前值,从异常退出时则可由SPSR来恢复CPSR。
User模式和System模式不属于异常模式,它们没有SPSR,当在这两种模式下访问SPSR,结果是未知的。

2.6 CPSR各标志位含义

31 30 29 28 27 26 7 6 5 4 3 2 1 0
N Z C V Q DNM(RAZ) I F T M4 M3 M2 M1 M0

N(Negative)—设置成当前指令运算结果的bit[31]的值。当两个有符号整数运算时,N=1运算结果为负数,N=0运算结果为正。

Z(Zero)—Z=1运算结果为零;Z=0表示运算的结果不为零。对于CMP指令,Z=1表示进行比较的两个数大小相等。

C(Carried out)—分四种情况讨论
1)在加法指令中(包括比较指令CMP),当结果产生进位,则C=1,表示无符号运算发生上溢出;其他情况C=0。
2)在减法指令中(包括减法指令CMP),当运算发生借位,则C=0,表示无符号运算发生下溢出;其他情况下C=1。
3)对于包含移位操作的非加减运算指令,C中包含最后一次溢出的位的数值
4)对于其他非加减运算指令,C位的值通常不受影响
V(oVerflow)—对于加减运算指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1符号为溢出;通常其他指令不影响V位。

Q—在ARM V5的E系列处理器中,CPSR的bit[27]称为Q标识位,主要用于指示增强的DSP指令是否发生了溢出。同样的spsr的bit[27]位也称为Q标识位,用于在异常中断发生时保存和恢复CPSR中的Q标识位。在ARM V5以前的版本及ARM V5的非E系列的处理器中,Q标识位没有被定义。

I和F—当I=1时禁止IRQ中断,当F=1时禁止FIQ中断

T—对于ARM V4以更高版本的T系列ARM处理器,T=0表示执行ARM指令;T=1表示执行Thumb指令
对于ARM V5以及更高版本的非T系列处理器,T=0表示执行ARM指令;T=1表示强制下一条执行的指令产生未定指令中断

M[4:0]—定义了的ARM工作模式,具体见1中表CSPR[4:0]定义的ARM工作模式

3.3 汇编指令

由于ARM的指令非常多,本文仅列举常见的一些汇编指令,更多的指令格式,请参考其他资料。

3.3.1 数据处理指令

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

3.3.2 cpsr访问指令

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

3.3.3 跳转(分支)指令

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

3.3.4 访存指令

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

3.3.5 软中断指令

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

3.3.6 其他

本人有ARM相关的学习资料若干份,这些都是非常经典使用的学习材料,感兴趣的可以扫码VX联系我。

4 更多分享

欢迎关注我的github仓库01workstation,日常分享一些开发笔记和项目实战,欢迎指正问题。

同时也非常欢迎关注我的CSDN主页和专栏:

【CSDN主页:架构师李肯】

【RT-Thread主页:架构师李肯】

【C/C++语言编程专栏】

【GCC专栏】

【信息安全专栏】

【RT-Thread开发笔记】

【freeRTOS开发笔记】

【BLE蓝牙开发笔记】

【ARM开发笔记】

【RISC-V开发笔记】

有问题的话,可以跟我讨论,知无不答,谢谢大家。

5 参考链接

  • ARM寻址方式
  • ARM寄存器
  • ARM指令

以上参考资料,由本人整理,但来源于网络,侵删!

【汇编实战开发笔记】ARM汇编基础的三大块知识相关推荐

  1. 【汇编实战开发笔记】从汇编代码中找出一段普通的for循环变成“死循环”的根本原因(RT-Thread技术论坛优秀文章)

    文章目录 1 前言 2 问题描述 3 简单分析 4 场景再现 5 柳暗花明 6 找到证据 6.1 究竟是不是警告 6.2 盘根问底 6.3 解除风险 7 扩展延伸 7.1 RISC-V架构 7.2 8 ...

  2. 【嵌入式开发】 ARM 汇编 (指令分类 | 伪指令 | 协处理器访问指令)

    作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42408137  转载请著名出处 本博客相关文档下载 :  -- A ...

  3. linux 嵌入式汇编 adc,嵌入式Linux ARM汇编(四)——ARM汇编程序设计

    嵌入式Linux ARM汇编(四)--ARM汇编程序设计 汇编程序有顺序.循环.分支.子程序四种结构形式. 一.顺序结构 程序实例: AREA Buf,DATA,READWRITE;定义数据段Buf ...

  4. 【Visual C++】游戏开发笔记十七 游戏基础算法(一) 游戏随机系统初步

    本系列文章由zhmxy555编写,转载请注明出处.http://blog.csdn.net/zhmxy555/article/details/7468011 作者:毛星云    邮箱: happyli ...

  5. 【Visual C++】游戏开发笔记十七 游戏基础算法 一 游戏随机系统初步

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 本系列文章由zhm ...

  6. arm export 汇编_灵活使用ARM汇编的WEAK关键字 (INPORT,EXPORT)---应该是在keil环境下,iar等还不知道...

    转载于:http://blog.csdn.net/norains/article/details/5954459 //========================================= ...

  7. linux 汇编与arm汇编,C语言与ARM汇编混编

    __asm__ __volatile__内嵌汇编用法简述 在阅读C/C++原码时经常会遇到内联汇编的情况,下面简要介绍下__asm__ __volatile__内嵌汇编用法.因为我们华清远见教学平台是 ...

  8. Egret实战开发笔记,飞行射击游戏(六)

    今天是开发飞行射击游戏第五天,玩家多类型子弹及状态和关卡模式. 简介 实现玩家特殊子弹,激光,追踪导弹. 玩家多状态 下方飞出 正常游戏 胜利等待 胜利飞出 以及 玩家保护 和 关卡切换 实现效果 本 ...

  9. Egret实战开发笔记,飞行射击游戏(二)

    简介 Egret实战开发,记录每天的学习进度,欢迎和我一起学习交流~ 目录 简介 实现目标 一.实现子弹类 二.工厂设计模式 三.子弹管理类ZDManager 实现目标 今天是开发飞行射击游戏第二天, ...

最新文章

  1. Python:列表前加*的作用
  2. 记一次数据库查询语句的优化
  3. python基础教程第二版答案-《Python基础教程》(第2版修订版)中要注意的地方...
  4. MPLS自身的优点所带来的网络便捷—Vecloud微云
  5. return 函数
  6. 《好未来编程题》删除公共字符
  7. 使用MyEclipse简单调用WebServices
  8. c语言中把时间拷到字符串中,C语言中将日期和时间以字符串格式输出的方法
  9. cogs62 [HNOI2004] 宠物收养所
  10. 深圳大学计算机科学考研,深圳大学考研计算机专业要多少分数会被百分百录取...
  11. linux syslog日志服务
  12. 【优化分类】基于matlab粒子群算法优化支持向量机分类(多输入多分类)【含Matlab源码 1559期】
  13. linux文件映射mmap
  14. 菜鸟的Hadoop快速入门
  15. asp.net铁路安全预警与决策支持系统
  16. 电子工程师最全面试题大全
  17. 测试@Test启动报错解决方案
  18. PAT 1082 射击比赛 python
  19. 数据如何变成知识,第 2 部分 数据湖和数据沼泽
  20. 大数据面试重点之kafka(七)

热门文章

  1. 思科交换机命令大全 二
  2. RK3399Pro/AR9201对比
  3. WebApi后端框架Token身份认证,Api接口Token验证
  4. Android摄像头开发:拍照后添加相框,融合相框和图片为一副 图片
  5. 2010年最抢手的热门职业
  6. ipdb调试常用的命令
  7. 守护城市魅力,平安智慧城市的数字化答卷
  8. radius服务器未响应,中国科学院地球环境研究所安全软件电子竞价成交公告
  9. 利用jsdoc和idea加速javascript开发(二)
  10. 《心理瘦身不反弹》公开出版问世