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。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

破局 AI 2.0 时代:利用 AI 提升自我核心竞争力

文章目录 破局 AI 2.0 时代:利用 AI 提升自我核心竞争力1. AI 2.0 时代1.1 特点1.2 发展1.3 影响 2. AI 2.0 时代的机遇 & 挑战2.1 AI 对行业市场的冲击2.2 挑战变为机遇2.3 不同场景下的 AI 效能提升2.3.1 自动化办公任务2.3.2 提升学习效率2.3.3 创意生成与内…

SpringBoot彩蛋之定制启动画面

写在前面 在日常开发中,我们经常会看到各种各样的启动画面。例如以下几种 ① spring项目启动画面 ② mybatisplus启动画面 ③若依项目启动画面 还有很多各式各样好看的启动画面,那么怎么定制这些启动画面呢? 一、小试牛刀 ① 新建一个Spr…

【分布式系统三】监控平台Zabbix对接grafana(截图详细版)

目录 一.安装grafana并启动 二.浏览器访问 三.导入zabbix数据,对接grafana 四.如何导入模版 以前两篇博客为基础 【分布式系统】监控平台Zabbix介绍与部署(命令截图版)-CSDN博客 【分布式系统】监控平台Zabbix自定义模版配置-CSDN博客 …

前端面试题(CSS篇五)

一、设备像素、css 像素、设备独立像素、dpr、ppi 之间的区别? 设备像素指的是物理像素,一般手机的分辨率指的就是设备像素,一个设备的设备像素是不可变的。 css像素和设备独立像素是等价的,不管在何种分辨率的设备上,…

网络连接线相关问题

问题1; 直通线为什么两头都是T568B?是否可以两台T5568A?或者任意线序,只需两头一致? 不行,施工规范规定。(原因;网线最长距离100m,实际用起来要把网线包管,走…

Kafka第四篇——生产数据总体概括,源码解析分区策略,数据收集器,Sender发送线程,key值

目录 流程图以及总体概述 拦截器 分区器以及分区计算策略 为啥进行分区计算? producer生产者怎么知道有哪些分区? 分区计算 如何自定义实现分区器? 想说的在图里啦!宝宝!💡 ​编辑 如果key值忘记传递了呢&a…

前端后花园周刊vol.18-React Native 称唯一推荐的社区框架是Expo

⚡️行业动态 React Native 团队推荐使用 Expo 框架构建应用程序 React Native 发文称:唯一推荐的社区框架是Expo,Expo 的开发者从 React Native 早期就开始支持 React Native 生态系统,相信 Expo 提供的开发者体验是同类中最好的。 &…

vscode调试教程

VSCode调试 VSCode Debuggers VSCode使用launch.json进行细粒度的控制,可以启动程序或将其附加到复杂的调试场景中 打开Run and Debug视图Ctrl Shift D 点击create a launch.json file,选择C(GDB/LLDB) 会在工作目录自动创建.vscode/launch.json文…

简单的基追踪一维信号降噪方法(MATLAB 2018)

基追踪法是基于冗余过完备字典下的一种信号稀疏表示方法。该方法具有可提高信号的稀疏性、实现阈值降噪和提高时频分辨率等优点。基追踪法采用表示系数的范数作为信号来度量稀疏性,通过最小化l型范数将信号稀疏表示问题定义为一类有约束的极值问题,进而转…

【linux服务器】大语言模型实战教程:LLMS大模型部署到个人服务器或嵌入式开发板(保姆级教学)

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引言 说到大语言模型相信大家都不会陌生,大型语言模型(LLMs)是人工智能文本处理的主要类型,也现在最流行的人工智能…

julia系列17: tsp问题代码整理

1. 常用库和基础函数 这里是优化版的函数: using TSPLIB,LKH,Distances,PyPlot MaxNum 10000 tspreadTSPLIB(:att48) dist [round.(Int,euclidean(tsp.nodes[i,:],tsp.nodes[j,:])) for i in 1:tsp.dimension,j in 1:tsp.dimension]; pos(tsp::TSP,t::Vector{In…

Games101学习笔记 Lecture17 Materials and Appearances

Lecture17 Materials and Appearances 材质 BRDF一、Diffuse/Lambertian Material二、Glossy Material三、Ideal reflective/ refractive Material (BSDF)1.镜面反射2.镜面折射3.菲涅尔项 Fresnel 四、Microfacet BRDF 微表面五、Isotropic / Anisotropic Materials (BRDFs)An…

python - 文件 / 永久存储:pickle / 异常处理

一.文件 利用help(open)可以看到open()函数的定义: >>> help(open) Help on built-in function open in module _io:open(file, moder, buffering-1, encodingNone, errorsNone, newlineNone, closefdTrue, openerNone) 默认打开模式是’rt’&#xff0…

王者荣耀与和平精英的语音识别不准确怎么办?分享一次意想不到的解决经历!

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 完整经历 📒🔍 问题初现 🔍🔎 排查之路:从绝望到希望的转折 🔎🎉 顿悟时刻:原来是“她”的恶作剧 🎉⚓️ 相关链接 ⚓️📖 介绍 📖 作为一位打字速度惊人的玩家,我向来自豪于能在王者荣耀和和平精英等游戏…

Three.js机器人与星系动态场景(四):封装Threejs业务组件

实际在写业务的时候不会在每个组件里都写几十行的threejs的初始化工作。我们可以 将通用的threejs的场景、相机、render、轨道控制器等进行统一初始化。同时将非主体的函数提到组件外部,通过import导入进组件。将业务逻辑主体更清晰一些。下面的代码是基于reactthre…

DHCP与TCP的简单解析

目录 一、DHCP 1.1 DHCP概述 1.2 DHCP的优势 1.3 DHCP的模式与分配方式***** 1.3.1 DHCP的模式:C/S模式(客户机与服务器模式) 1.3.2 DHCP的分配方式 1.4 DHCP的租约过程及原理 1.4.1 DHCP的工作原理***** 1.4.2 更新租约原理***** …

智慧校园-基础平台功能总体概述

智慧校园基础平台是现代教育信息化的核心,它集成了系统管理、基础数据、系统监控、系统工具、流程管理等关键功能,构建了一个全面、智能、安全的校园生态系统。系统管理部分,通过权限管理和用户管理,实现了对用户访问权限的精细化…

使用qt creator配置msvc环境(不需要安装shit一样的宇宙第一IDE vs的哈)

1. 背景 习惯使用Qt编程的童鞋,尤其是linux下开发Qt的童鞋一般都是使用qt creator作为首选IDE的,通常在windows上使用Qt用qt creator作为IDE的话一般编译器有mingw和msvc两种,使用mingw版本和在linux下的方式基本上一样十分简单,不…

warning: GOPATH set to GOROOT (D:\go) has no effect

warning: GOPATH set to GOROOT (D:\go) has no effect gopath 设置一下,并且不要和 goroot 设置成同一个目录

【carla】ubuntu安装carla环境

我们可以通过查看 CARLA 的 GitHub release 页面来找到最新版本的下载链接。 下载 CARLA 压缩包 访问 CARLA Releases 页面: CARLA Releases on GitHub 查找最新版本: 找到最新的版本,点击下载,第一个压缩包 3. 解压 CARLA 包&…