ARM汇编与机器码、汇编指令

文章目录

1. CISC与RISC指令集

2. ARM汇编指令

3. 汇编与机器码

4. 汇编指令格式

5. MOV指令

6. BL指令

7. B指令

8. ADD/SUB指令

9. LDR/STR指令


1. CISC与RISC指令集

根据指令的复杂度,所有CPU可以分为两类:

CISC(Complex Instruction Set Computer)

  • 描述:复杂指令集计算机,具有较多且复杂的指令。
  • 代表:如x86架构的处理器。
  • 特点
    • 指令复杂,单条指令可执行多个操作。
    • 指令长度不固定,可能会占用多个CPU周期。
    • 适合编写复杂的操作,但指令解码复杂,功耗较高。

RISC(Reduced Instruction Set Computing)

  • 描述:精简指令集计算机,指令集较少且简单。
  • 代表:如ARM架构的处理器。
  • 特点
    • 指令简单,每条指令通常只执行一个操作。
    • 指令长度固定,通常为32位,执行速度快。
    • 易于设计和优化,适合嵌入式系统和移动设备。

加法运算示例

以加法运算 a = a + b 为例,说明CISC和RISC的区别:

CISC指令

使用CISC指令集计算机,如x86提供的加法指令,可以通过一条指令完成如下4步操作:

  • 读取a
  • 读取b
  • 计算a + b
  • 把结果写回a
ADD a, b  ; 将b加到a并将结果存储在a中

这条指令可能需要多个CPU周期来完成。

RISC指令

RISC指令集不提供“单条指令”完成加法操作,需要调用多条简单指令:

LDR R0, [a]    ; 将a的值加载到寄存器R0
LDR R1, [b]    ; 将b的值加载到寄存器R1
ADD R0, R0, R1 ; 将R0和R1的值相加,结果存储在R0
STR R0, [a]    ; 将结果存储回a

这些指令每条只执行一个操作,执行速度快,指令解码简单。

2. ARM汇编指令

ARMv7-A/R指令集

  • ARM指令集:大约150条基础指令。这些指令主要用于32位操作。
  • Thumb指令集:约60条指令,用于优化代码密度的16位操作。
  • Thumb-2指令集:结合了Thumb和ARM指令的特点,增加了额外的指令,使得Thumb指令集扩展到100多条指令。

ARMv8-A指令集

  • A64指令集:用于64位操作,有超过100条指令。
  • A32指令集:与ARMv7的ARM指令集向下兼容。
  • T32指令集:与ARMv7的Thumb-2指令集向下兼容。

常见指令类别

  • 数据处理指令:包括算术运算、逻辑运算、位操作等,例如ADD, SUB, MUL, AND, ORR。
  • 加载和存储指令:用于内存和寄存器之间的数据传输,例如LDR, STR。
  • 分支指令:用于改变程序执行的顺序,例如B, BL, BX。
  • 系统指令:控制系统级操作,例如MRS, MSR。
  • SIMD和浮点指令:用于多媒体处理和科学计算,例如VADD, VMUL。

ARM芯片属于精简指令集计算机(RISC),它所用的指令有以下特点:

对内存只有读、写指令

  • LDR:加载指令,从内存读取数据到寄存器。
  • STR:存储指令,从寄存器写数据到内存。

对于数据的运算在CPU内部实现

  • ADD:加法指令,在寄存器之间进行加法运算。
  • SUB:减法指令,在寄存器之间进行减法运算。
  • MUL:乘法指令,在寄存器之间进行乘法运算。

使用RISC指令的CPU复杂度小

  • 指令长度固定:通常为32位,执行速度快。
  • 易于设计和优化:指令解码简单,功耗低。

在实际应用中,使用RISC架构的ARM处理器进行编程时,通常使用高级编程语言(如C语言)。编译器会将C语言代码翻译成ARM汇编指令,然后进一步翻译成机器码运行在处理器上。

示例代码:

int a = 0x12;
int b = 0x34;
int result;result = a + b;

编译器生成的汇编指令:

LDR R0, =0x12      ; 将立即数0x12加载到寄存器R0
LDR R1, =0x34      ; 将立即数0x34加载到寄存器R1
ADD R2, R0, R1     ; 将R0和R1的值相加,结果存储在R2
STR R2, [result]   ; 将结果存储到变量result中

3. 汇编与机器码

在STM32单片机中,使用ARM Cortex-M系列处理器的汇编指令,可以直接对内存和寄存器进行操作。通过一系列的简单汇编指令,我们可以完成复杂的运算操作。下面我们详细解释各个步骤及对应的汇编指令。

示例:计算乘积

我们以加法运算 a = a + b 为例,详细解析每一步的操作及其对应的汇编指令。

假设我们有两个数 ab,它们的值分别为 0x12 和 0x34,我们希望计算它们的乘积 c = a * b,并将结果存储在内存中。

汇编代码示例

; 初始化
mov r3, #addr_a   ; 将变量 a 的地址传给 CPU 寄存器 r3
ldr r0, [r3]      ; 从 r3 所指的内存把 a 的值读进 CPU 寄存器 r0
mov r4, #addr_b   ; 将变量 b 的地址传给 CPU 寄存器 r4
ldr r1, [r4]      ; 从 r4 所指的内存把 b 的值读进 CPU 寄存器 r1; 计算乘积
mul r2, r0, r1    ; 将 r0 和 r1 的值相乘,结果存储在 r2; 存储结果
mov r5, #addr_c   ; 将变量 c 的地址传给 CPU 寄存器 r5
str r2, [r5]      ; 将 r2 的值写入 r5 所指的内存

在上面的示例中,movldrstr 等指令都是汇编指令,或称为“助记符”,帮助我们记忆和理解这些操作。这些指令实际上是一个个数字,我们去记这些数字的难度很大,所以使用这些助记符来简化理解。

助记符与机器码的关系

在机器码的指令格式中,操作码(opcode)用来表示不同的指令。例如:

  • mov 对应的操作码是 0010
  • add 对应的操作码是 0001

每个助记符指令都对应特定的机器码,这些机器码由操作码和操作数组成,通常占用32位。例如:

mov r1, r0  ; 机器码可能为 00100000 00000001 00000000

 

汇编指令与机器码的转换

汇编指令和机器码的关系是固定的,但不同的编译器可能会对一些指令进行优化或使用不同的格式。在实际编程中,机器码通过汇编器或编译器自动生成。

; 初始化
mov r3, #addr_a   ; 机器码: 0xE3A03000  ; 将立即数 addr_a 加载到寄存器 r3
ldr r0, [r3]      ; 机器码: 0xE5930000  ; 从内存地址 r3 加载数据到寄存器 r0
mov r4, #addr_b   ; 机器码: 0xE3A04000  ; 将立即数 addr_b 加载到寄存器 r4
ldr r1, [r4]      ; 机器码: 0xE5941000  ; 从内存地址 r4 加载数据到寄存器 r1; 计算乘积
mul r2, r0, r1    ; 机器码: 0xE0000291  ; 将 r0 和 r1 的值相乘,结果存储在 r2; 存储结果
mov r5, #addr_c   ; 机器码: 0xE3A05000  ; 将立即数 addr_c 加载到寄存器 r5
str r2, [r5]      ; 机器码: 0xE5852000  ; 将寄存器 r2 的值存储到内存地址 r5

MOV指令

  • 汇编指令:mov r3, #addr_a
  • 机器码:0xE3A03000
  • 解释:E3A0表示MOV指令,3表示目标寄存器r30000表示立即数#addr_a

 

4. 汇编指令格式

在ARM汇编语言中,每条指令都有一个固定的格式,便于CPU解释和执行。这些指令由标签(label)、指令(instruction)和注释(comment)组成,下面我们详细解释各部分的含义和使用方法。

label: instruction @ comment
  • label(标签):标签表示代码中的一个位置,通常用于跳转(branch)指令的目标地址。标签以冒号(:)结尾。
  • instruction(指令):汇编指令或伪指令,用于操作寄存器、内存和CPU状态。
addnum: mov r0, #0 @ 将 R0 寄存器设置成 0
  • addnum 是一个标签,表示当前指令的位置。

  • mov r0, #0 是一条指令,表示将立即数0加载到寄存器R0中。

5. MOV指令

在ARM架构中,MOV指令用于将一个寄存器的值移动到另一个寄存器,或者将一个常数加载到寄存器。

示例指令:

mov r1, #10  @ 将10赋值给寄存器r1,即r1=10

指令执行过程

  1. 取指:首先,CPU从内存的addrA地址取出机器码e3a0100a(即mov r1, #10指令)。

  2. 译码:CPU解释取出的机器码,发现它是一条MOV指令。

  3. 执行:CPU将立即数10赋值给寄存器R1。

机器码解析

机器码e3a0100a的各个位的含义如下

  • cond(条件码):[31:28]位,值为0xe,表示总是执行,即条件码为AL(Always)。
  • I:第25位,值为1,表示操作数是立即数。
  • OpCode:操作码,表示MOV指令。
  • S:第20位,值为0,表示不更新条件标志位。
  • Rn:[19:16]位,值为0,MOV指令中无关。
  • Rd:[15:12]位,值为1,表示目的寄存器为R1。
  • Operand2(操作数2):[11:0]位,立即数0x0a,即10。

对应的二进制:

1110 0011 1010 0000 0001 0000 0000 1010
  • 1110:条件码,为AL(Always)。
  • 0011 1010:MOV指令的操作码部分。
  • 0000:Rn字段,不适用。
  • 0001:Rd字段,表示寄存器R1。
  • 0000 0000 1010:立即数10的二进制表示。

6. BL指令

在ARM汇编中,BL(Branch with Link)指令用于跳转到指定的标签地址,同时将返回地址记录在LR(Link Register)寄存器里。

示例代码:

1  bl test_tag      @ 跳转到test_tag
2  mov r1, #10      @ 将10赋值给r1
3
4 test_tag:
5  mov r3, #0       @ 将0赋值给r3
6  mov pc, lr       @ 返回调用点,继续执行mov r1, #10指令
  1. 取指

    • CPU从内存地址addrA取出机器码eb000000(即bl test_tag指令),执行后PC跳转到test_tag标签位置,即内存的addrA+8地址。同时将内存的addrA+4地址存储在寄存器LR中。
  2. 执行标签位置的指令

    • CPU从内存地址addrA+8取出机器码e3a03000(即mov r3, #0指令),执行后,将寄存器R3的值设为0。
    • CPU从内存地址addrA+12取出机器码e1a0f00e(即mov pc, lr指令),执行后,PC跳转到内存地址addrA+4
    • CPU从内存地址addrA+4取出机器码e3a0100a(即mov r1, #10指令),执行后,将寄存器R1的值设为10。

BL指令的机器码

机器码eb000000

  • cond(条件码):[31:28]位,值为0xe,表示总是执行,即条件码为AL(Always)。
  • Offset(偏移量):[23:0]位,表示PC与标签的偏移值。

在此例子中,偏移值为0,这是因为ARM采用三级流水线的方式,即取指、译码、执行指令。执行addrA地址的bl test_tag指令时,PC已经指向addrA+8,所以偏移值要设置为0。

偏移值的计算

在ARM架构中,BL指令的偏移量计算是基于当前指令地址(即PC的值)与目标地址(标签地址)之间的差值,偏移量表示为目标地址与当前地址的差值除以4。

例如:

  • 当前指令地址为addrA,下一条指令地址为addrA+4
  • 偏移量imm24表示为目标地址与当前指令地址的差值除以4。

因此,当bl test_tag指令执行时:

  • PC值为addrA+8,目标地址为addrA+8test_tag标签的地址),所以偏移量为0。

7. B指令

B 指令用于无条件跳转到指定的标签地址。执行该指令时,程序计数器(PC)被更新为目标地址。相比 BL 指令,它不会保存下一条指令的地址到 LR 寄存器。

示例代码:

b test_tag
mov r1, #10
test_tag:
mov r3, #0

指令执行过程:

  1. 第 1 行,CPU 执行 b test_tag 指令,跳转到 test_tag 标签处执行 mov r3, #0 指令。
  2. b 指令不保存返回地址,不同于 BL 指令。

8. ADD/SUB指令

示例代码:

mov r1, #10    ; 将 10 赋值给寄存器 r1
add r2, r1, #4 ; r2 = r1 + 4
sub r2, r1, #4 ; r2 = r1 - 4

指令执行过程

  1. 取指

    • CPU 从内存的 addrA 地址取出机器码 e3a0100a(即 mov r1, #10 指令),执行后,CPU 内部寄存器 R1 等于 10。
  2. 译码、执行

    • CPU 从内存的 addrA+4 地址取出机器码 e2812004(即 add r2, r1, #4 指令),执行后,CPU 内部寄存器 R2 等于 14。
    • CPU 从内存的 addrA+8 地址取出机器码 e2412004(即 sub r2, r1, #4 指令),执行后,CPU 内部寄存器 R2 等于 6。

机器码:

add r2, r1, #4

  • 机器码:e2812004
  • 解析:指令各位的解析如下:
    • [31:28] 位是条件码 0xe
    • [19:16] 位是源寄存器 R1,即 0x1;
    • [15:12] 位是目标寄存器 R2,即 0x2;
    • [11:0] 位是立即数 4,即 0x004。
指令机器码条件码目标寄存器源寄存器立即数
mov r1, #10e3a0100a0xeR1 (0x1)N/A0x00a
add r2, r1, #4e28120040xeR2 (0x2)R1 (0x1)0x004
sub r2, r1, #4e24120040xeR2 (0x2)R1 (0x1)0x004

9. LDR/STR指令

LDR(Load Register)和STR(Store Register)指令是ARM指令集中用来从内存加载数据到寄存器和从寄存器存储数据到内存的指令。以下是一个示例汇编代码及其执行过程。

代码示例:

mov r0, #0x400    @ 将立即数 0x400 存入寄存器 r0
mov r1, #0xa      @ 将立即数 0xa 存入寄存器 r1
str r1, [r0]      @ 将寄存器 r1 中的值 0xa 存入寄存器 r0 指向的地址(0x400)
ldr r2, [r0]      @ 将寄存器 r0 指向地址 0x400 的值(0xa)加载到寄存器 r2

指令执行过程:

mov r0, #0x400:将立即数0x400加载到寄存器R0。

  • CPU从内存地址addrA处取出机器码e3a00b01,执行后,CPU内部寄存器R0等于0x400。

mov r1, #0xa:将立即数0xa加载到寄存器R1。

  • CPU从内存地址addrA+4处取出机器码e3a0100a,执行后,CPU内部寄存器R1等于0xa。

str r1, [r0]:将寄存器R1的值存储到寄存器R0指向的内存地址0x400。

  • CPU从内存地址addrA+8处取出机器码e5801000,执行后,寄存器R1的0xa值存储到地址0x400。

ldr r2, [r0]:将寄存器R0指向地址0x400的数据加载到寄存器R2。

  • CPU从内存地址addrA+12处取出机器码e5902000,执行后,寄存器R0指向地址0x400的数据加载到寄存器R2,R2等于0xa。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/42772.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#——多态详情

多态 多态: 是同一个行为,具有多个不同表现形式或形态的能力 多态分为两种 : 静态性多态: 函数重载,符号重载动态性多态: 虚方法,抽象类,接口 静态多态 在编译时,函数和对象的连接机制被称为早期绑定,…

知识图谱的符号表示

1、基于图的表示建模 2、有效标记图 3、属性图表示方法的优点和去点 4、RDF是什么?表达是有限的 5、OWL,本体语言 6、OWL有很多家族 7、属性图、RDF\三元组、关系图 ---------------------------PPT---------------------

已解决 javax.xml.transform.TransformerFactoryConfigurationError 异常的正确解决方法,亲测有效!!!

已解决 javax.xml.transform.TransformerFactoryConfigurationError 异常的正确解决方法,亲测有效!!! 目录 一、问题分析 二、报错原因 三、解决思路 四、解决方法 五、总结 博主v:XiaoMing_Java 博主v&#x…

【微服务网关——服务发现】

1.服务发现 1.1 介绍 服务发现是指用注册中心来记录服务信息,以便其他服务快速查找已注册服务服务发现分类: 客户端服务发现服务端服务发现 1.2 客户端服务发现 客户端服务发现(Client-side Service Discovery)是一种微服务架构中的模式…

Vine: 一种全新定义 Vue 函数式组件的解决方案

7月6日的 vue confg 大会上 ShenQingchuan 大佬介绍了他的 Vue Vine 项目, 一种全新定义 Vue 函数式组件的解决方案。 和 React 的函数式组件有异曲同工之妙,写起来直接起飞了。 让我们来快速体验一下 vine, 看看到底给我们带来了哪些惊喜吧…

[Python]配置邮件服务,发送邮件

本文以163邮件系统为例,登录之后,点击设置,开启如下设置项。 即可使用代码发送邮件,并携带附件。 开启SMTP 普通邮件 import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart# 1…

[算法] 优先算法(四):滑动窗口(下)

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…

20240708 每日AI必读资讯

🤖破解ChatGPT惊人耗电!DeepMind新算法训练提效13倍,能耗暴降10倍 - 谷歌DeepMind研究团队提出了一种加快AI训练的新方法——多模态对比学习与联合示例选择(JEST),大大减少了所需的计算资源和时间。 - JE…

Java线程的创建·启动和休眠

一.线程的创建和启动 Java中创建线程的两种方式 ◆继承java.lang.Thread类 ◆实现java.lang.Runnable接口 ◆使用线程的步骤 继承Thread类创建线程 ◆自定义线程类继承自Thread类 ◆重写run()方法,编写线程执行体 ◆创建线程对象,调用start()方法启动…

目标检测YOLO实战应用案例100讲-基于深度学习的无人机影像小目标识别(续)

目录 3.2 实验平台和环境 3.3 实验评价指标 3.4 基础框架YOLOv5在无人机数据集上的实验 3.4.1 实验结果 3.4.2 结果分析 4基于深度学习的无人机影像目标检测算法 4.1 基于改进YOLOv5的小目标检测算法研究 4.1.1 增加注意力机制 4.1.2 增加检测层 4.1.3多尺…

2024年 春秋杯 网络安全联赛夏季赛 Web方向 题解WirteUp 部分

brother 题目描述:web哥,打点容易提权难。 打点就是最简单的SSTI。 执行下find / -user root -perm -4000 -print 2>/dev/null找一下具备suid权限的命令 /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/bin/chsh /usr/bin/gpasswd /usr/bin/n…

互联网十万个为什么之什么是数据备份?

数据备份是按照一定的备份频率创建数据副本的过程,将重要的数据复制到其它位置或者存储介质,并对生成的副本保留一定的时长。备份通常储存在不同的物理介质或云端,以确保数据的连续性和完整性。有效的备份策略至关重要,以防止数据…

macos 10.15系统下载包,macOS Catalina for mac

macOS Catalina 让你喜欢的种种 Mac 体验都更进一步。你可以领略音乐、播客这两款全新 Mac app 的表演;在 Mac 上畅享各款自己心爱的 iPad app;拿起 iPad 和 Apple Pencil,拓展工作空间,释放创意灵感;再打开那些平时常…

【STL】vector的模拟实现

目录 vector的介绍和使用 vector的介绍 vector的使用 构造函数 迭代器 空间增长问题 vector的增删查改等 vector的迭代器失效问题 vector的模拟实现 insert reserve push_back push_front resize erase pop_back pop_front 代码 vector的介绍和使用 vecto…

【PB案例学习笔记】-29制作一个调用帮助文档的小功能

写在前面 这是PB案例学习笔记系列文章的第29篇,该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习,提高编程技巧,以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码,小凡都上传到了gite…

个人视角,社会影响力:自媒体的魅力所在

随着数字化时代的到来,自媒体正成为信息传播领域的一场革命。个人视角与社会影响力的结合,赋予了自媒体独特的魅力。在传统媒体受限制的同时,自媒体为每个人提供了表达自己观点和思想的自由。个体的真实视角使得自媒体在信息传播中发挥着重要…

14-40 剑和诗人14 - 为什么机器学习需要合成数据

​​​​​​ 数据是人工智能的命脉。如果没有高质量、有代表性的训练数据,我们的机器学习模型将毫无用处。但随着神经网络规模越来越大、人工智能项目越来越雄心勃勃,人们对数据的需求也越来越大,我们面临着一场危机——现实世界的数据收集和…

如何优化 PostgreSQL 中对于复杂数学计算的查询?

文章目录 一、理解复杂数学计算的特点二、优化原则(一)索引优化(二)查询重写(三)数据库配置调整(四)使用数据库内置函数的优势 三、具体的优化方案和示例(一)…

华为开源自研AI框架昇思MindSpore应用案例:FCN图像语义分割

Mask R-CNN MaskRCNN是一种概念简单、灵活、通用的目标实例分割框架,在检测出图像中目标的同时,还为每一个实例生成高质量掩码。这种称为Mask R-CNN的方法,通过添加与现有边框检测分支平行的预测目标掩码分支,达到扩展Faster R-CN…

leetcode判断二分图

判断二分图 图的问题肯定要用到深度优先遍历或者广度优先遍历,但又不是单纯的深度优先遍历算法和广度优先遍历算法,而是需要在遍历的过程中加入与解决题目相关的逻辑。 题干中说了,这个图可能不是连通图,这个提示有什么作用呢&a…