0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【RT-Thread学习笔记】ARM汇编基础的三大块知识

嵌入式物联网开发 来源:嵌入式物联网开发 作者:嵌入式物联网开发 2022-07-30 10:59 次阅读

1 前言

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

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

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

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

2 ARM知识图谱

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

image-20220130222634953

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使用完全相同的物理寄存器。

ARM寄存器介绍

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模式下访问的R8~R12都是同一个物理寄存器(共5个物理寄存器);在FIQ模式下,访问的R8fiq~R12fiq是另外独立的物理寄存器(共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中系统调用

4 更多分享

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

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

【CSDN主页:架构师李肯】

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

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

【GCC专栏】

信息安全专栏】

【RT-Thread开发笔记】

freeRTOS开发笔记】

【BLE蓝牙开发笔记】

【ARM开发笔记】

RISC-V开发笔记】

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

5 参考链接

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

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


审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • ARM
    ARM
    +关注

    关注

    134

    文章

    8648

    浏览量

    361756
  • 嵌入式
    +关注

    关注

    4981

    文章

    18274

    浏览量

    288367
  • RT-Thread
    +关注

    关注

    31

    文章

    1148

    浏览量

    38866
收藏 人收藏

    评论

    相关推荐

    RT-Thread学习笔记】使用scons命令生成静态库

    RT-Thread学习笔记】如何使用scons 命令中buildlib的生成静态库?
    的头像 发表于 07-27 09:13 4752次阅读
    【<b class='flag-5'>RT-Thread</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>】使用scons命令生成静态库

    RT-Thread学习笔记】80x86汇编基础的三大块知识

    RT-Thread学习笔记】80x86汇编基础的三大块知识
    的头像 发表于 07-30 10:57 1615次阅读
    【<b class='flag-5'>RT-Thread</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>】80x86<b class='flag-5'>汇编</b>基础的<b class='flag-5'>三大块</b><b class='flag-5'>知识</b>

    RT-Thread学习笔记】RISC-V汇编基础三大块知识

    RT-Thread学习笔记】RISC-V汇编基础的三大块知识
    的头像 发表于 07-30 11:01 2371次阅读
    【<b class='flag-5'>RT-Thread</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>】RISC-V<b class='flag-5'>汇编</b>基础<b class='flag-5'>三大块</b><b class='flag-5'>知识</b>

    RT-Thread学习笔记】一种C语言宏定义的写法

    RT-Thread学习笔记】一种C语言宏定义的写法
    的头像 发表于 07-30 13:41 1940次阅读
    【<b class='flag-5'>RT-Thread</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>】一种C语言宏定义的写法

    RT-Thread Nano入门学习笔记

    RT-Thread Nano入门学习笔记
    发表于 11-26 12:36 20次下载
    <b class='flag-5'>RT-Thread</b> Nano入门<b class='flag-5'>学习</b><b class='flag-5'>笔记</b>

    RT-Thread 内核学习笔记 - 理解defunct僵尸线程

    RT-Thread 内核学习笔记 - 内核对象rt_objectRT-Thread 内核学习笔记
    发表于 01-25 18:19 8次下载
    <b class='flag-5'>RT-Thread</b> 内核<b class='flag-5'>学习</b><b class='flag-5'>笔记</b> - 理解defunct僵尸线程

    RT-Thread 内核学习笔记 - 设备模型rt_device的理解

    RT-Thread 内核学习笔记 - 内核对象rt_objectRT-Thread 内核学习笔记
    发表于 01-25 18:19 8次下载
    <b class='flag-5'>RT-Thread</b> 内核<b class='flag-5'>学习</b><b class='flag-5'>笔记</b> - 设备模型<b class='flag-5'>rt</b>_device的理解

    RT-Thread 内核学习笔记 - 内核对象链表结构深入理解

    RT-Thread 内核学习笔记 - 内核对象rt_objectRT-Thread 内核学习笔记
    发表于 01-25 18:23 6次下载
    <b class='flag-5'>RT-Thread</b> 内核<b class='flag-5'>学习</b><b class='flag-5'>笔记</b> - 内核对象链表结构深入理解

    RT-Thread全球技术大会:RT-Thread底层汇编及在arm与riscv上的差异

    开发者秦韦忠,在RT-Thread全球技术大会上,以RT-Thread底层汇编及在arm与riscv上的差异为主题进行了详细的教程说明。
    的头像 发表于 05-28 09:56 1439次阅读
    <b class='flag-5'>RT-Thread</b>全球技术大会:<b class='flag-5'>RT-Thread</b>底层<b class='flag-5'>汇编</b>及在<b class='flag-5'>arm</b>与riscv上的差异

    RT-Threadarm与riscv上的两点差异

    RT-Thread全球大会上,介绍了RT-Threadarm与riscv上的两点差异如下:
    的头像 发表于 05-28 10:35 1311次阅读
    <b class='flag-5'>RT-Thread</b>在<b class='flag-5'>arm</b>与riscv上的两点差异

    RT-Thread学习笔记 RT-Thread的架构概述

    的种种优越之处。RT-Thread 是一款完全由国内团队开发维护的嵌入式实时操作系统(RTOS),具有完全的自主知识产权。经过 16 个年头的沉淀,伴随着物联网的兴起,它正演变成一个功能强大、组件丰富
    的头像 发表于 07-09 11:27 3990次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b> <b class='flag-5'>RT-Thread</b>的架构概述

    RT-Thread学习笔记】Makefile的FORCE

    RT-Thread学习笔记】十分钟学会Makefile的FORCE
    的头像 发表于 07-30 13:55 1651次阅读
    【<b class='flag-5'>RT-Thread</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>】Makefile的FORCE

    RT-Thread学习笔记】如何抓取终端的网络报文

    RT-Thread学习笔记】如何抓取终端的网络报文?
    的头像 发表于 07-30 13:57 2154次阅读
    【<b class='flag-5'>RT-Thread</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>】如何抓取终端的网络报文

    RT-Thread学习笔记】用memwatch排除内存泄露

    RT-Thread学习笔记】使用memwatch排除内存泄露
    的头像 发表于 07-30 14:01 1725次阅读
    【<b class='flag-5'>RT-Thread</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b>】用memwatch排除内存泄露

    基于RT-Thread Studio学习

    前期准备:从官网下载 RT-Thread Studio,弄个账号登陆,开启rt-thread学习之旅。
    的头像 发表于 05-15 11:00 2576次阅读
    基于<b class='flag-5'>RT-Thread</b> Studio<b class='flag-5'>学习</b>