当前位置: 首页 > ds >正文

ARM 裸机开发 知识点

目录

一、基础概念

1.1 机器码

1.2 汇编指令

1.3 汇编指令集

定义

分类

1.4 架构

定义

主流架构

1.5 内核 - CPU 的核心

1.6 处理器

分类

MCU 和 MPU 的区别

问:使用过哪些MCU?

结构图

STM32MP157AAA 型号的命名规则和含义

二、ARM公司发展史

三、复杂指令集与精简指令集

3.1 复杂指令集

概念

3.2 精简指令集

概念

3.3 修改 Thumb 指令集为 ARM 指令集

四、内核中的寄存器组织

4.1 六大存储类型

定义变量的流程

分类

register:寄存器存储类型

volatile

4.2 ARM 处理器(内核)的工作模式

① Cortex-M 核的工作模式

② Cortex-A 核的工作模式

4.3 寄存器组织

五、特殊功能寄存器

5.1 R13 寄存器(SP寄存器)

5.2 R14 寄存器(LR 寄存器)

5.3 R15 寄存器(PC寄存器)

SP、LR、PC 寄存器总结

5.4 CPSR寄存器

CPSR寄存器(4个字节32位)的高四位与低八位

5.5 SPSR寄存器

六、汇编指令

6.1 汇编指令的分类

基础汇编指令

进阶汇编指令

6.2 汇编指令基本格式

6.3 数据搬移指令(赋值指令)

指令码

指令格式

测试代码

立即数

如何判断一个数是否是立即数

例:

有效数

ldr 伪指令

6.4 移位操作运算指令

指令码

指令格式

测试代码

6.5 位运算操作指令

指令码

指令格式

测试代码

练习

我的答案

6.6 算数运算指令

指令格式

测试代码


一、基础概念

1.1 机器码

机器码就是机器或计算机能够识别的0和1的二进制格式

1.2 汇编指令

一条具备特殊功能的指令

1.3 汇编指令集

定义

多条不同功能的汇编指令的集合

分类

  1. x86-64 汇编指令集
  2. ARM 汇编指令集
  3. ZEN 汇编指令集
  4. PowerPC 汇编指令集
  5. RISC-V 汇编指令集
  6. …………

1.4 架构

定义

架构是汇编指令集别名,不同的汇编指令集可以设计出不同的架构

主流架构

1.5 内核 - CPU 的核心

不同的架构可以设计出不同的内核

以下架构都是ARM公司基于arm汇编指令集设计出的不同的架构
arm-v1~v6架构:目前已经淘汰
arm-v7架构:支持32位汇编指令集(ARM课程所使用的STM32MP157AAA这款芯片就是通过arm-v7架构设计而来的)
arm-v8架构:支持64位汇编指令集,向下兼容32位汇编指令集
arm-v9架构:最新的架构,主要应用在性能要求比较高的设备上基于arm-v7架构设计出了Cortex-M4内核
基于arm-v8架构设计出了Cortex-A9内核
基于arm-v9架构设计出了Cortex-X5内核ARM公司设计的内核分类:Cortex-M系列内核(M3、M4、M33......)    ------    应用在功能相对简单(低功耗产品)Cortex-A系列内核(A7、A8、A9......)     ------    之前应用在手机、电脑上Cortex-R系列内核                        ------    应用在对实时性要求比价高的产品上Cortex-X系列内核                        ------    最新的、性能最高的系列

ARM课程使用的芯片:STM32MP157AAA芯片(通过arm-v7架构设计) = Cortex-A7核 + Cortex-M4核 
单片机课程使用的芯片:STM32U575RIT6芯片 = Cortex-M33内核

1.6 处理器

分类

  • CPU:中央处理器
  • MCU:微控制单元(微控制器)
  • MPU:微处理单元(微处理器)
  • SOC:SOC 的全称是 System on a Chip,中文通常译为 “系统级芯片”。

MCU 和 MPU 的区别

  1. MCU:传统意义上的单片机,不支持使用操作系统(目前可以使用小行实时操作系统),性能和功耗低。
  2. MPU:高性能的处理器,支持使用操作系统(linux、Android……)
  3. 对于ARM公司
  • MCU为Cortex-M系列内核
  • MPU为Cortex-A / X系列内核

问:使用过哪些MCU?

使用过 STM32F103、STM32F407、STM32MP157A、STM32U575……

结构图

STM32MP157AAA 型号的命名规则和含义

ST:公司名字M:MCU(微控制器)32:支持32位的汇编指令集MP1xx:芯片型号(MP1系列:MP157、MP158....)AAA:芯片性能

二、ARM公司发展史

ARM前身为艾康电脑(Acorn),于1978年,英国剑桥成立,大学的孵化物。

  • 1980年代晚期,苹果开始与艾康合作,开发新版ARM核心。
  • 1985年,艾康开发出全球第一款商用RISC(精简指令集)处理器,即ARM1,针对于PC市场,还没有嵌入式呢!!!
  • 1990年,艾康财务危机,受苹果和VLSI(最早做超大规模集成电路的公司)的投资,成立独立子公司:Advanced RISC Machines(ARM), ARM公司正式成立面世。
  • 2004年,发布ARMv7架构的Cortex系列处理器,同时推出Cortex-M3。
  • 2005年,发布Cortex-A8处理器。
  • 2007年,发布Cortex-M1和Cortex-A9
  • 2009年,实现Cortex-A9、发布Cortex-M0
  • 2010年,推出Cortex-M4(F)、成立Linaro (ARM公司牵头成立的公共组织,专门做ARM处理器在Linux平台上的一些软件的开发和移植), 推出Cortex-A15 MPcore高性能处理器(性能比较高了,但是发热量很大哦)。
  • 2011年,推出32位 Cortex-A7 处理器,ARMv8发布
  • 2012年,开始推出64位处理器。推出 Cortex-M0+、ARM 首款64位处理器架构 Cortex-A53、Cortex-A57 架构。全球第一款64位ARM手机iPhone5s。
  • 2013年,推出32位 Cortex-A12 处理器架构
  • 2014年,推出 Cortex-M7(F) 微控制器架构;32位 Cortex-A17处理器架构。
  • 2015年,推出64位 Cortex-A35、Cortex-A72 处理器架构。
  • 2016年,推出 Cortex-M23 、Cortex-M33(F) 微控制器架构;32位 Cortex-A32 处理器架构;64位 Cortex-A73 处理器架构。
  • 2017年,推出64位 Cortex-A55 、Cortex-A75 处理器架构。
  • 2018年,推出微控制器 Cortex-M35P;64位 Cortex-A76 处理器架构。
  • 2016年,日本软银收购ARM公司
  • 2020年,NVIDIA想收购(没成功)
  • 现在的ARM公司不再做芯片,只做内核的技术支持和授权

三、复杂指令集与精简指令集

3.1 复杂指令集

概念

复杂指令集中的汇编指令的指令宽度指令周期不固定

  • 指令宽度:每条汇编指令占用内存空间的大小
  • 指令周期:每条汇编指令被执行需要的时间

X86汇编指令集就是复杂指令集

反汇编终端指令:objdump

  • 作用:将二进制编码格式的文件转换为汇编指令格式的文件

3.2 精简指令集

概念

精简指令集的汇编指令的指令周期指令宽度固定

  • ARM汇编指令集、Mips汇编指令集、RISC-V汇编指令集、PowerPC汇编指令集……

ARM汇编指令存在很多子集,其中有一个Thumb汇编指令集

  • 默认状态时,自动选择使用Thumb汇编指令
  • Thumb汇编指令集大小为 16 位,即指令宽度都是 16 位(2 字节)
  • ARM汇编指令集大小为 32 位,即指令宽度都是 32 位(4 字节)

Cortex-M内核大多使用 Thumb 汇编指令集

Cortex-A内核大多使用 ARM 汇编指令集

3.3 修改 Thumb 指令集为 ARM 指令集

        使用arm-linux-gnueabihf-gcc交叉编译器时, 可以添加 -mthumb 或 -marm 选项来指定使用的指令集。-marm 选项明确指示编译器生成 ARM 指令集的代码。

修改完成后


四、内核中的寄存器组织

4.1 六大存储类型

定义变量的流程

存储类型 + 数据类型 + 变量名;

分类

auto、static、const、extern、volatileregister

register:寄存器存储类型

  1. 使用register修饰变量时,变量会直接存储到核内寄存器
  2. 无法通过内存地址进行访问,只能通过寄存器编号进行访问
  3. 访问速度快,但寄存器个数有限

volatile

作用:防止编译器对代码进行优化直接从内存中取最新的值

应用场景:

  1.  多线程使用同一资源时
  2. 单片机的开发

        volatile 修饰的变量不会利用高速缓存(DCache)来暂存数据,而是直接与内存进行数据交互。为什么要添加 volatile 呢?因为如果不添加,会存在隐患

        变量 a 可能会被数据高速缓存区(DCache)暂存,当线程 1、2、3 访问 a 时,可能读取到缓存区的旧值而非最新值。比如线程 1、2 都修改了 a,但由于缓存的存在,线程 3 在执行 c = a + 1 时,可能获取的是旧值,导致结果混乱

        而添加 volatile 后,会直接跳过缓存,直接操作内存强制每次读写操作都直接与内存交互,这样就能读取到最新的数据。无论哪个线程修改了 a 的值,其他线程都能立刻看到内存里的最新值,避免因缓存“留存旧数据”而导致计算错误(例如线程 3 能获取到线程 1、2 改过的 a,而不是缓存里的旧值)。

        另外,编译 main 函数所在的程序,生成二进制文件后,将二进制文件下载到 STM32MP157AAA 芯片中。在该芯片(基于 Cortex - A7 内核)里,ICache 是指令高速缓存区,DCache 是数据高速缓存区。被 volatile 修饰的变量不再通过高速缓存暂存数据,而是直接和内存进行数据交互,像在 main 函数中,volatile int a = 10;,线程 1 执行 a = 1;、线程 2 执行 a = 2;、线程 3 执行 c = a + 1; 时,都能基于内存中的最新 a 值进行操作。

4.2 ARM 处理器(内核)的工作模式

① Cortex-M 核的工作模式

  1. 线程模式(执行用户代码,类似main函数)
  2. 异常模式

② Cortex-A 核的工作模式

非特权模式

  • User模式(用户模式,执行用户代码)

特权模式

  • 非异常模式:Sys模式(系统模式 / 管理员模式)
  • 异常模式:
    • IRQ模式:普通中断异常模式
    • FIQ模式:快速中断异常模式
    • SVC模式:超级管理异常模式
    • ABT模式:访问中止异常模式
    • UDF / UNF模式:未定义异常模式

以上是使用 ARM-v7 架构的工作模式

ARM-v8 架构之后,有两种新的工作模式

  • MON模式:安全监管模式
  • HYP模式:虚拟化技术模式

4.3 寄存器组织

寄存器组织图
ARM 处理器不同运行模式下的寄存器映射图

根据上图可知:

  1. 每个小方块都是一个寄存器,每个寄存器的大小都是4个字节
  2. 黑色字体的寄存器是实际存在的寄存器,灰色字体的寄存器是实际不存在的寄存器
  3. 白色底的寄存器是公用的寄存器,蓝色底的寄存器是私有的寄存器(只有在对应模式下可以使用的私有寄存器)
  4. 实际可以操作的寄存器一共有43个(大小:43*4个字节)
  5. 上述寄存器均为核内寄存器(无法通过内存地址进行访问,只能通过寄存器编号进行访问,如R0、R1、R2....) 核外寄存器可以通过内存地址进行访问


五、特殊功能寄存器

5.1 R13 寄存器(SP寄存器)

the stack pointer

        |

栈指针寄存器

        |

用于保存栈区的一篇内存空间地址


        跳转执行函数 func 前将 r1 和 r2 寄存器中的值保存压入到 SP 寄存器所指向的一片内存栈地址空间中,函数执行完毕后,将保存的值恢复到 r1 和 r2 中,从而实现 C 语言中对于局部变量的操作。

5.2 R14 寄存器(LR 寄存器)

the linking register

        |

链接寄存器

        |

用于保存函数的返回地址


        在调用 func 函数的过程中,会将返回地址(即r0 = r1 + r2)保存到 LR 寄存器中

5.3 R15 寄存器(PC寄存器)

the program conter register

                |

程序计数寄存器

                |

用于保存下一条需要执行的汇编指令的地址


        在 ARM 指令集(32 位指令)下,PC 寄存器在执行一条指令后会自动 + 4 以指向下一条指令;若为 Thumb 指令集(16 位指令),则通常自动 + 2函数返回时,LR 寄存器中预先存储了返回地址,通过BX LRMOV PC, LR等指令将 LR 的值传递给 PC,使程序跳转回返回地址继续执行。

SP、LR、PC 寄存器总结

- SP寄存器:用于保存栈空间的一片地址,用于实现C语言中的局部变量

- LR寄存器:用于保存函数的返回地址,用于实现C语言中的函数返回

- PC寄存器:用于保存下一条需要执行的汇编指令的地址,用于实现C语言语句的一条一条执行

- 综合使用实现函数之间的跳转

5.4 CPSR寄存器

the current program status register

                |

当前程序状态寄存器

                |

用于保存当前程序的状态

CPSR寄存器(4个字节32位)的高四位与低八位

高 4 位

N - 31位 - 负数标志位 - 比较两个数的大小

  • 取决于最近一次影响标志位的运算(ADD、SUB、CMP等)结果的最高位:
    • 最高位结果为1(即负数,计算机中补码表示),N = 1
    • 最高位结果为0(即正数或 0 ),N = 0

Z - 30位 - 零标志位 - 判断两数相等

  • 当指令运算结果为 0 时,Z = 1;否则,Z = 0

C - 29位 - 进位 / 借位标志位 - 比较无符号数的大小

  • 无符号数加法中,结果超出位数范围产生进位C = 1
  • 无符号数减法中,被减数小于减数产生借位C = 0

- 28位 - 溢出标志位 / 符号标志位

  • 有符号数运算时,结果超出了有符号数的表示范围,对符号位产生了变化,V = 1;否则 V = 0

低 8 位 - 控制位

I - 7位 - IRQ模式使能位 / IRQ模式屏蔽位 / 中断禁止位

  • I = 1 -> 禁止IRQ普通中断模式
  • I = 0 -> 允许IRQ普通中断模式

F - 6位 - FIQ模式使能位 / FIQ模式屏蔽位 / 快速中断禁止位

  • F = 1 -> 禁止FIQ快速中断模式
  • F = 0 -> 允许FIQ快速中断模式

T - 5位 - 状态位 / ARM状态屏蔽位 / Thumb 状态位

  • T = 1 -> 处理器屏蔽 ARM 状态,运行 Thumb 指令集(16 位指令)
  • T = 0 -> 不屏蔽 ARM 状态,运行 ARM 指令集(32位指令)

M - [4 : 0] 位 - 模式位 / 工作模式位

  • 10000 -> User 模式
  • 10001 -> FIQ 模式
  • 10010 -> IRQ 模式
  • 10011 -> Supervisor(SVC)模式
  • 10110 -> Monitor(MON)模式
  • 10111 -> Abort(ABT)模式
  • 11010 -> Hyp(HYP)模式
  • 11011 -> Undef(UND)模式
  • 11111 -> System(SYS)模式

5.5 SPSR寄存器

the save program status register

                        |

        备份程序状态寄存器

                        |

        用于备份程序的状态

        在USER模式(非特权模式)切换到执行IRQ(异常模式)代码时,将CPSR寄存器当前的值存放至SPSR寄存器中,异常模式代码执行结束后,需要切换回原用户代码继续执行,将SPSR寄存器中的值取回还原至CPSR中,从而实现不同模式的切换


六、汇编指令

6.1 汇编指令的分类

基础汇编指令

 ① 数据操作指令

  1. 数据搬移指令(赋值指令 = )
  2. 移位运算指令(<<、>>)
  3. 位运算指令(&、|、~、^)
  4. 算数运算指令(+、-、*、/)
  5. 比较指令(<、>、==、!=)

② 跳转指令

进阶汇编指令

③ 单寄存器内存读写指令

④ 栈指针寄存器内存读写指令(包含多寄存器内存读写指令)

⑤ CPSR 特殊功能寄存器内存读写指令

⑥swi软中断指令

6.2 汇编指令基本格式

{opcode}{cond}{s}        Rd, Rn, oprand_shifter2

{opcode}        --->        指令码,汇编指令的名字


{cond}        --->        条件码,用于指定指令在满足特定条件时才会执行,省略则指令无条件执行


{s}        --->        当指令带有该后缀时,会影响程序状态寄存器(CPSR)中的 N Z C V 标志位,不带该后缀则不会影响


Rd        --->        目标寄存器,用于存放指令执行后的结果


Rn        --->        第一操作寄存器,源寄存器之一,相当于左操作数,通常是操作数所在的寄存器


oprand_shifter2        --->        可选第二操作数,可以是 立即数普通寄存器经过移位的寄存器(如ADD  R0, R1, R2, LSL  #2

注意:

1、{opcode}{cond}{s} 指令码、条件码、状态位连在一起写的,不允许出现空格

2、Rd, Rn, oprand_shifter2 目标寄存器、第一操作寄存器、第二操作数连在一起写,但是需要使用 , 隔开

3、{opcode}{cond}{s} 和 Rd, Rn, oprand_shifter2 这两个部分中间需要由空格隔开

4、汇编指令没有以 分号 ; 结尾,所以一条汇编指令写一行

5、汇编指令没有大小写区别

        mov r0, #0xff ==== MOV R0, #0XFF ==== MoV r0, #0xFF

        这三句话是一样的

6、在当前汇编文件中,使用的编译器支持的注释方式:

        6.1 单行注释 @ (不同的编译器支持的注释方式不同,可能有; , #......)

        6.2 多行注释

                /**/

                .if 0/1 .else .endif

6.3 数据搬移指令(赋值指令)

指令码

mov        直接赋值指令mvn        按位取反后赋值

指令格式

mov / mvn  Rd, oprand_shifter2

 无第一操作寄存器,只有目标寄存器和第二操作数

测试代码

.text		.global _start		_start:			mov r0, #0xff	@ 解释:将0xff赋值到R0寄存器中@ 如果使用赋值指令时,第二操作数是一个立即数@ 需要在他的前面加上#mvn r1, #0xff	@ 解释:将0xff全部按位取反后,赋值给r1寄存器@ r1 = ~(0xff) = 0xffffff00mov r2, #(-0xff)	@ -0xff(存储的补码,正数源码和补码是一致的,负数需要计算)@ 源码:0x800000ff@ 反码:0xffffff00@ 补码:0xffffff01stop:			b stop		
.end		

立即数

一条汇编代码占 4 个字节空间

movr0{cond}{s}Rn

0~7 位是mov可直接操作的数值范围

0~255

0x00~0xff

如何判断一个数是否是立即数
  1. 需要判断的数为 A
  2. 可以在 0x00 ~ 0xFF 之间找到一个数 B
  3. 数 B 可以通过 循环右移偶数位 是的其 与数 A 相等

则数 A 为立即数

例:

判断0XFF是否是立即数

1、数A = 0XFF = 0B 0000 0000 0000 0000 0000 0000 1111 1111

2、数B = 0XFF = 0B 0000 0000 0000 0000 0000 0000 1111 1111

3、循环右移偶数位:32位

判断0XFFF是否是立即数

1、数A = 0XFFF = 0B 0000 0000 0000 0000 0000 11111 1111 1111

2、数B = 0XFF = 0B 0000 0000 0000 0000 0000 0000 1111 1111 (找不到数B)

3、0XFFF不是一个立即数

判断0X1F000000是否是立即数

1、数A = 0X1F000000 = 0B 0001 1111 0000 0000 0000 0000 0000 0000

2、数B = 0X1F = 0B 0000 0000 0000 0000 0000 0000 0001 1111 (循环右移8位)

3、数B = 0XF8 = 0B 0000 0000 0000 0000 0000 0000 1111 1000 (循环右移11位)

4、数B = 0X7C = 0B 0000 0000 0000 0000 0000 0000 0111 1100 (循环右移10位)

可能存在多个数B,但是只要有一个数B符合要求,当前的数A就是一个立即数

有效数

一个数全部按位取反后,可以得到一个立即数,则这个数就是一个 有效数

ldr 伪指令

将一个较大范围的 32 位立即数加载到寄存器中

可以实现 0x00000000 ~ 0xFFFFFFFF 之间任意数值的赋值操作

6.4 移位操作运算指令

指令码

lsl(logical Shift Left) ---> 逻辑左移 / 无符号数左移 ---> 高位移出,低位补 0lsr(Logical Shift Right) ---> 逻辑右移 / 无符号数右移 ---> 低位移出,高位补 0ror(Rotate Right) ---> 循环右移     ---> 低位移出,补到高位asr(Arithmetic Shift Right) ---> 算数右移 / 有符号数右移 ---> 低位移出,高位补符号位

指令格式

lsl/lsr/ror/asr Rd, Rn, oprand_shifter2

测试代码

/***********************2、移位运算指令**************************/mov r0, #0xfflsl r1, r0, #8	@ 将r0寄存器中的值逻辑左移8位后赋值给r1寄存器@ r1 = r0 << 8 = 0xff00lsr r2, r1, #12	@ 将r1寄存器中的值逻辑右移12位后赋值给r2寄存器@ r2 = r1 >> 12 = 0xfror r3, r2, #4	@ 将r2寄存器中的值循环右移4位后赋值给r3寄存器@ r3 = 0xf0000000asr r4, r3, #4	@ 将r3寄存器中的值算术右移4位后赋值给r4寄存器@ r4 = 0xff@ 高位补符号位指的是所有高位都需要补符号位,而不是只有最高位补符号位/***********************2、第二操作数的所有情况**************************/@ 第二操作数可以是一个立即数mov r0, #0xff	@ 解释:将0xff赋值给r0寄存器中@ 第二操作数可以是一个普通寄存器mov r1, r0		@ 解释:将r0寄存器中的值赋值给r1寄存器中@ 第二操作数可以是一个经过移位的寄存器mov r2, r1, lsl #4	@ 解释:将r1寄存器中的值逻辑左移4位后赋值给r2寄存器@ 上述汇编指令的作用和这条lsl r2, r1, #4汇编指令的作用是一致的

6.5 位运算操作指令

指令码

and    --->    按位与(&)
orr    --->    按位或(|)
eor    --->    按位异或(^)
mvn    --->    按位取反(~)

口诀:

        与 0 清 0,与 1 不变

        或 1 置 1,或 0 不变

        异或 1 取反,异或 0 不变

指令格式

and/orr/eor/mvn    Rd, Rn, oprand_shifter2

测试代码

	/***********************4、位运算操作指令**************************/@ 32位数:@ 31									  0@  **** **** **** **** **** **** **** **** mov r0, #0xff@ 目的:将r0寄存器中的第[3]位清0,其他位不变,最后赋值给r0寄存器@ c语言写法:r0 = r0 & (~(0x1 << 3))and r0, r0, #(~(0x1 << 3))		@ r0 = 0xf7@ 目的:将r0寄存器中的第[3]位置1,其他位不变,最后赋值给r0寄存器orr r0, r0, #(0x1 << 3)

练习

        @假设你不知道r0寄存器中的值ldr r0, =0x12345678@ 31					                 0@  **** **** **** **** **** **** **** **** @ 1> 将r0寄存器的第[3]位清0,保持其他位不变and r0, r0, #(~(0x1 << 3))@ 2> 将r0寄存器的第[29]位置1,保持其他位不变orr r0, r0, #(0x1 << 29)@ 3> 将r0寄存器的第[7:4]位清0,保持其他位不变and r0, r0, #(~(0xf << 4))@ and r0, r0, #(~(0b1111 << 4))@ 4> 将r0寄存器的第[15:8]位置1,保持其他位不变orr r0, r0, #(0xff << 8)@ orr r0, r0, #(0x0000ff00)@ 5> 将r0寄存器的第[3:0]位按位取反,保持其他位不变eor r0, r0, #(0xf << 0)@ 6> 将r0寄存器的第[11:4]位修改为10101011,保持其他位不变@ 推荐使用先清0再置1and r0, r0, #(~(0xff << 4))orr r0, r0, #(0b10101011 << 4)	@ orr r0, r0, #(0xab << 4)@ 也可以先置1再清0orr r0, r0, #(0xab << 4)and r0, r0, #(~(0x54 << 4))

我的答案

.text 
.global _start _start:ldr r0,=0x12345678@1>将r0寄存器的第[3]位清0,保持其他位不变and r0, r0, #(~(0x1<<3))@2>将r0寄存器的第[29]位置1,保持其他位不变orr r0, r0, #(0x1<<29)@3>将r0寄存器的第[7:4]位清0,保持其他位不变and r0, r0, #(~(0xf<<4))@4>将r0寄存器的第[15:8]位置1,保持其他位不变orr r0, r0, #(0xf<<8)@5>将r0寄存器的第[3:0]位按位取反,保持其他位不变eor r0, r0, #(0xf)@6>将r0寄存器的第[11:4]位修改为10101011,保持其他位不变and r0, r0, #(~(0xff<<4))orr r0, r0, #(0xAB<<4)stop:b stop.end

6.6 算数运算指令

add ---> 基础加法指令,不影响 CPSR 寄存器的 C 位;adc ---> 带进位加法指令,执行指令时要加上 CPSR 中的 C 位,进位时 C = 1;sub ---> 基础减法指令,不影响 CPSR 寄存器的 C 位;sbc ---> 带借位减法指令,执行指令时要多减 (1-C) ,借位时 C = 0;mul ---> 乘法指令;div ---> 除法指令,需要在 ARM-v8 及以上架构使用;

指令格式

add/adc/sub/abc/mul/div    Rd, Rn, oprand_shifter2

测试代码

	/***********************5、算数运算操作指令**************************/mov r1, #0x1mov r2, #0x3@ add r3, r1, r2	@ r3 = 0x1 + 0x3 = 0x4@ sub r4, r2, r1	@ r4 = 0x3 - 0x1 = 0x2@ 模拟两个64位数相减@ r1寄存器存放第一个64位数的高32位,r2寄存器存放第一个64位数的低32位@ r3寄存器存放第二个64位数的高32位,r4寄存器存放第二个64位数的低32位@ r5寄存器中存放相减后的高32位数,r6寄存器存放相减后的低32位数mov r1, #0x5mov r2, #0x2mov r3, #0x1mov r4, #0x8@ 先低位相减subs r6, r2, r4		@ 此时需要使用到s状态位@ 由于当前指令的执行结果产生了借位@ 并且高32位运算时,需要使用到产生借位后的C位@ r6 = r2 - r4 = 0x2 - 0x8 = 0x2 - 0x2 - 0x6@ = 0x0 - 0x6 = 0x0 - 0x1 - 0x5@ = 0xffffffff - 0x5 = 0xfffffffasbc r5, r1, r3		@ 此时需要使用到sbc@ 由于此处高32位相减时,需要多减去一个借位@ r5 = r1 - r3 - c位 = 0x5 - 0x1 - 0x1 = 0x3@ 注意:不管c位存放的是0/1@ 只要c位产生了借位,就需要多减一个0x1@ 只要c位产生了进位,就需要多加一个0x1@ 模拟两个64位数相加@ r1寄存器存放第一个64位数的高32位,r2寄存器存放第一个64位数的低32位@ r3寄存器存放第二个64位数的高32位,r4寄存器存放第二个64位数的低32位@ r5寄存器中存放相加后的高32位数,r6寄存器存放相加后的低32位数mov r1, #0x1mov r2, #0xfffffffemov r3, #0x2mov r4, #0x4adds r6, r2, r4	@ r6 = 0xfffffffe + 0x4@ = 0xfffffffe + 0x1 + 0x3@ = 0xffffffff + 0x3@ = 0xffffffff + 0x1 + 0x2@ = 0x0 + 0x2 = 0x2adc r5, r1, r3 @ r5 = r1 + r3 + c位 = 0x1 + 0x2 + 0x1 = 0x4

http://www.xdnf.cn/news/19388.html

相关文章:

  • 豌豆压缩怎么用?3步避免网盘资源被和谐 网盘压缩包总被和谐?豌豆压缩实测解析 豌豆压缩避坑指南:敏感资源存储必读
  • 雷卯国产化之SE3401完全替代AOS的AO3401
  • 数字签名 digital signature
  • 年化225%,回撤9%,夏普4.32,3积分可查看参数
  • Java 常见异常系列:ClassNotFoundException 类找不到
  • Java 学习笔记(基础篇12)
  • 学习Python中Selenium模块的基本用法(10:浏览器操作)
  • 让演化可编程:XLang 与可逆计算的结构化范式
  • [ZJCTF 2019]NiZhuanSiWei
  • 第2节:项目前期准备
  • C++抽象类
  • 【Python 后端框架】总结
  • Nginx反向代理与负载均衡
  • 基于单片机指纹考勤系统/智能考勤
  • DeepSeek应用技巧-通过MCP打造数据分析助手
  • YOLOv11 训练参数全解析:一文掌握 epochs、batch、optimizer 调优技巧
  • kali下sqlmap更新失败问题
  • PB-重装系统后,重新注册ole控件,pb中窗口控件失效的问题。
  • 不用公网IP也能?cpolar实现Web-Check远程安全检测(1)
  • 2025年09月计算机二级MySQL选择题每日一练——第十二期
  • 数据结构 | 深度解析二叉树的基本原理
  • 云存储(参考自腾讯云计算工程师认证)
  • 整体设计 的语言设计:通用模型语言的标准模板语言的规格模式语言--含输出(腾讯元宝答问)
  • 漏洞挖掘-信息收集教程
  • 阿里云营业执照OCR接口的PHP实现与技术解析:从签名机制到企业级应用
  • Jdk动态代理 Cglib动态代理
  • Linux 定时器:工作原理与实现机制深入分析
  • STL库——list(类模拟实现)
  • 复制VMware虚拟机后的网络配置
  • 算法---动态规划(持续更新学习)