【FreeRTOS】ARM架构汇编实例
目录
- ARM架构简明教程
- 1. ARM架构
- 电脑的组成
- 1.2 RISC
- 1.2 提出问题
- 1.3 CPU内部寄存器
- 1.4 汇编指令
- 2. C函数的反汇编
学习视频
【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS(FreeRTOS教程 基于STM32,以实际项目为导向)】 https://www.bilibili.com/video/BV1Jw411i7Fz/?p=9&share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933
ARM架构简明教程
1. ARM架构
电脑的组成
对于单片机,叫SoC system on chip,在芯片上有完整的系统
芯片集成了CPU 内存 硬盘(flash)
内存:读出数据,写入数据
计算都是在CPU内完成的
1.2 RISC
ARM芯片属于精简指令集计算机(RISC:Reduced Instruction Set Computing),它所用的指令比较简单,有如下特点:
① 对内存只有读、写指令
② 对于数据的运算是在CPU内部实现
③ 使用RISC指令的CPU复杂度小一点,易于设计
对于上图所示的乘法运算a = a * b,在RISC中要使用4条汇编指令:
① 读内存a
② 读内存b
③ 计算a*b
④ 把结果写入内存
1.2 提出问题
问题:在CPU内部,用什么来保存a、b、a*b ?
回答:寄存器 R0、R1、R2……
1.3 CPU内部寄存器
无论是cortex-M3/M4,
还是cortex-A7,
CPU内部都有R0、R1、……、R15寄存器;
它们可以用来“暂存”数据。
对于R13、R14、R15,还另有用途:
R13:别名SP(Stack Pointer),栈指针
R14:别名LR(Link Register),用来保存返回地址
R15:别名PC(Program Counter),程序计数器,表示当前指令地址,写入新值即可跳转
1.4 汇编指令
-
读内存:Load
# 示例 LDR R0, [R1, #4] ; 读地址"R1+4", 得到的4字节数据存入R0
Load R 读 四个字节,读R1+4的地址,读入的数据保存到R0里
其他指令:LDRB\LDRH
LDRB 读取一个字节 1Byte,LDRH 读取Half,2Bytes
-
写内存:Stroe
# 示例 STR R0, [R1, #4] ; 把R0的4字节数据写入地址"R1+4"
写内存 4个字节STR 把R0的4字节数据写到R1+4
写其他字节数
STRB 1byte
STRH half - 2bytes
读写指令经常用到,一定要掌握这两条指令
-
加减
ADD R0, R1, R2 ; R0=R1+R2 ADD R0, R0, #1 ; R0=R0+1 SUB R0, R1, R2 ; R0=R1-R2 SUB R0, R0, #1 ; R0=R0-1
-
比较
CMP R0, R1 ; 结果保存在PSR(程序状态寄存器)
结果保存到程序状态寄存器里
-
跳转
B main ; Branch, 直接跳转 BL main ; Branch and Link, 先把返回地址保存在LR寄存器里再跳转
跳转
B main; PC/R15=main的地址
BL main; 分为两个步骤
LR/R14=返回地址
PC/R15=main的地址
2. C函数的反汇编
C函数:
int add(volatile int a, volatile int b)
{volatile int sum;sum = a + b;return sum;
}
这段代码里用volatile int a,不要让编译器优化我们的程序
把这个函数复制,随便我们工程的放到一个地方
修改如下部分
void OLED_Test(void)
{int OLED_Count = 0;OLED_Init();// 清屏OLED_Clear();while (1){// 在(0, 0)打印'A'OLED_PutChar(0, 0, 'A');// 在(1, 0)打印'Y'OLED_PutChar(1, 0, 'Y');// 在第0列第2页打印一个字符串"Hello World!"OLED_PrintString(0, 2, "Hello World!");OLED_PrintSignedVal(6, 4, OLED_Count);OLED_Count = add(OLED_Count, 1); //OLED_Count ++ 看反汇编代码}
}
让Keil生成反汇编:
选择 魔术棒-uesr 示例图片
- 为例方便复制,制作反汇编的指令如下:
fromelf --text -a -c --output=xxx.dis xxx.axf
上面语句的作用是 用 xxx.axf 输出 xxx.dis 的反汇编
- 为了方便复制粘贴,先做好我自己的这行代码,自己的路径自己粘贴,方法在如下
- 在linker的窗口下,往下翻,就能找到linker的路径,复制粘贴到对应的位置即可
结合起来就是
fromelf --text -a -c --output=test.dis 01_freertos_template\01_freertos_template.axf
用01_freertos_template\01_freertos_template.axf ,输出test.dis的反汇编
粘贴到对应的位置
编译 看输出结果
这里很直观的看到输出了.dis文件
找到这个文件,用文本文档打开
OLED_Test0x08002a00: 2400 .$ MOVS r4,#00x08002a02: f7ffff01 .... BL OLED_Init ; 0x80028080x08002a06: f7fffeea .... BL OLED_Clear ; 0x80027de0x08002a0a: 2100 .! MOVS r1,#00x08002a0c: 2241 A" MOVS r2,#0x410x08002a0e: 4608 .F MOV r0,r10x08002a10: f7ffff9c .... BL OLED_PutChar ; 0x800294c0x08002a14: 2259 Y" MOVS r2,#0x590x08002a16: 2100 .! MOVS r1,#00x08002a18: 2001 . MOVS r0,#10x08002a1a: f7ffff97 .... BL OLED_PutChar ; 0x800294c0x08002a1e: a208 .. ADR r2,{pc}+0x22 ; 0x8002a400x08002a20: 2102 .! MOVS r1,#20x08002a22: 2000 . MOVS r0,#00x08002a24: f7ffff79 ..y. BL OLED_PrintString ; 0x800291a0x08002a28: 4622 "F MOV r2,r40x08002a2a: 2104 .! MOVS r1,#40x08002a2c: 2006 . MOVS r0,#60x08002a2e: f7ffff35 ..5. BL OLED_PrintSignedVal ; 0x800289c0x08002a32: 2101 .! MOVS r1,#10x08002a34: 4620 F MOV r0,r40x08002a36: f000fa7f .... BL add ; 0x8002f380x08002a3a: 4604 .F MOV r4,r00x08002a3c: e7e5 .. B 0x8002a0a ; OLED_Test + 10
add0x08002f38: b503 .. PUSH {r0,r1,lr}0x08002f3a: b081 .. SUB sp,sp,#40x08002f3c: e9dd0101 .... LDRD r0,r1,[sp,#4]0x08002f40: 4408 .D ADD r0,r0,r10x08002f42: 9000 .. STR r0,[sp,#0]0x08002f44: bd0e .. POP {r1-r3,pc}
i.main
main0x08002f46: f7fdfe77 ..w. BL HAL_Init ; 0x8000c380x08002f4a: f7fffe0f .... BL SystemClock_Config ; 0x8002b6c0x08002f4e: f7fffa1d .... BL MX_GPIO_Init ; 0x800238c0x08002f52: f7fffac3 .... BL MX_I2C1_Init ; 0x80024dc0x08002f56: f7fff9cf .... BL MX_ADC1_Init ; 0x80022f80x08002f5a: f7fffadf .... BL MX_SPI1_Init ; 0x800251c0x08002f5e: f7fffc1f .... BL MX_USB_PCD_Init ; 0x80027a00x08002f62: f7fffaff .... BL MX_TIM1_Init ; 0x80025640x08002f66: f7fffb65 ..e. BL MX_TIM2_Init ; 0x80026340x08002f6a: f7fffbc1 .... BL MX_TIM3_Init ; 0x80026f00x08002f6e: f7fffbfb .... BL MX_USART1_UART_Init ; 0x80027680x08002f72: f000f813 .... BL osKernelInitialize ; 0x8002f9c0x08002f76: f7fff9e7 .... BL MX_FREERTOS_Init ; 0x80023480x08002f7a: f000f82b ..+. BL osKernelStart ; 0x8002fd40x08002f7e: e7fe .. B 0x8002f7e ; main + 56
搜索add,要区分大小写!
C函数add
int add(volatile int a, volatile int b)
{volatile int sum;sum = a + b;return sum;
}
C函数add的反汇编代码如下:
i.addadd0x08002f34: b503 .. PUSH {r0,r1,lr}0x08002f36: b081 .. SUB sp,sp,#40x08002f38: e9dd0101 .... LDRD r0,r1,[sp,#4]0x08002f3c: 4408 .D ADD r0,r0,r10x08002f3e: 9000 .. STR r0,[sp,#0]0x08002f40: bd0e .. POP {r1-r3,pc}
add函数里的cnt参数保存在r0里,1保存在r1里,局部变量保存在栈里
对于单片机来说,在FLASH的地址上,保存这些数据
cpu会读取FLASH地址,得到对应的机器码,在cpu内部执行机器码,
cpu会读取FLASH地址,得到对应的机器码,在cpu内部执行机器码,
cpu会读取FLASH地址,得到对应的机器码,在cpu内部执行机器码,
……
从栈里把数值POP到R1R2R3,
仅仅是为了后面把LR的值POP到PC寄存器,仅
仅是为了恢复栈
以上可以看出,对于汇编代码,本质上,大多数汇编代码都是读取内存,写入内存,加加,减减,跳转
看起来很高大上的C语言的函数,在汇编里都是如此,读内存,写内存,加加,减减,跳转~
韦老师说这节课看不懂没关系,后面课程还会讲的
学习视频
【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS(FreeRTOS教程 基于STM32,以实际项目为导向)】 https://www.bilibili.com/video/BV1Jw411i7Fz/?p=9&share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933
相关文章:
【FreeRTOS】ARM架构汇编实例
目录 ARM架构简明教程1. ARM架构电脑的组成1.2 RISC1.2 提出问题1.3 CPU内部寄存器1.4 汇编指令 2. C函数的反汇编 学习视频 【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS(FreeRTOS教程 基于STM32,以实际项目为导向)】 https://www.…...
【Linux】常见指令的使用
文章目录 which指令stat 指令wc指令echo指令tree 指令whoami指令clear指令alias指令ls指令pwd指令cd 指令touch指令mkdir指令(重要)rmdir指令 && rm 指令(重要)man指令(重要)cp指令(重要…...
C#面:详细阐述什么是 DTO
DTO(Data Transfer Object)是一种设计模式,用于在不同层之间传输数据。它的主要目的是在应用程序的不同部分之间传递数据,而不是直接传递实体对象。DTO通常是一个简单的POCO(Plain Old CLR Object)…...
「TCP 重要机制」三次握手四次挥手
🎇个人主页:Ice_Sugar_7 🎇所属专栏:计网 🎇欢迎点赞收藏加关注哦! 三次握手&四次挥手 🍉连接管理🍌三次握手🍌意义🍌四次挥手🍌TCP 状态转换…...
Java数据库编程
引言 在现代应用开发中,与数据库交互是不可或缺的一部分。Java提供了JDBC(Java Database Connectivity) API,允许开发者方便地连接到数据库并执行SQL操作。本文将详细介绍Java数据库编程的基础知识,包括JDBC的基本概念…...
决策树算法介绍:原理与案例实现
一、引言 决策树是一种常用于分类和回归任务的机器学习算法,因其易于理解和解释的特点,在数据分析和挖掘领域有着广泛应用。本文将介绍决策树算法的基本原理,并通过一个具体案例展示如何实现和应用该算法。 二、决策树算法原理 1. 决策树结…...
业务代表模式
业务代表模式 引言 在软件工程中,设计模式是解决常见问题的经典解决方案。它们为开发人员提供了一种方法,以优雅和可重用的方式处理软件开发中的挑战。业务代表模式(Business Delegate Pattern)是一种行为设计模式,它主要关注于将业务逻辑与表示层(如用户界面)分离,以…...
LeetCode 算法:反转链表 c++
原题链接🔗:反转链表 难度:简单⭐️ 题目 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 示例 1: 输入:head [1,2,3,4,5] 输出:[5,4,3,2,1] 示例 2:…...
【多线程】Thread类及其基本用法
🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 文章目录 1. Java中多线程编程1.1 操作系统线程与Java线程1.2 简单使用多线程1.2.1 初步创建新线程代码1.2.2 理解每个…...
Springboot 整合 Flowable(一):使用 flowable-UI 绘制流程图
目录 一、Flowable简介 二、Flowable 与 Activiti 的区别 三、流程图的绘制(以员工请假流程图为例) 1、下载 flowable 的压缩包: 2、启动包中的 tomcat 3、登录页面 4、绘制结束,导出 bpmn20.xml文件 一、Flowable简介 Fl…...
课设--学生成绩管理系统(一)
欢迎来到 Papicatch的博客 文章目录 🍉技术核心 🍉引言 🍈标识 🍈背景 🍈项目概述 🍈 文档概述 🍉可行性分析的前提 🍈项目的要求 🍈项目的目标 🍈…...
thinkphp5模型的高级应用
ThinkPHP5 是一个基于 PHP 的轻量级框架,它提供了许多便利的功能来简化 Web 开发。在 ThinkPHP5 中,模型(Model)是 MVC(Model-View-Controller)架构中的重要组成部分,负责处理数据逻辑。以下是一…...
XML XSLT:技术与应用解析
XML XSLT:技术与应用解析 XML(可扩展标记语言)和XSLT(XML样式表转换语言)是现代信息技术中不可或缺的工具。本文将深入探讨XML和XSLT的概念、技术细节以及它们在实际应用中的作用。 XML简介 XML是一种用于存储和传输…...
嵌入式单片机中项目在线仿真工具分享
前段时间,无意间发现了一个不错的在线仿真工具(Wokwi),支持多种平台,支持市面上主流的开发板,比如:STM32、ESP32、Arduino、树莓派等。 还支持常见的传感器、显示器件(LCD、LED屏幕)等,还可以播放音乐、联网、逻辑分析仪等,关键还提供了很多实际项目的案例。 这款工…...
Unity动态添加聊天文本
1.创建一个滚动视图 2.调整滚动视图的位置并删掉这个 3.创建一个输入框和一个按钮 这里插一句一定要给content添加这个组件并设置单元格大小 4创建一个脚本并编写下面代码 using System.Collections; using System.Collections.Generic; using TMPro; using Unity.VisualScrip…...
力扣-2269. 找到一个数字的 K 美丽值
文章目录 力扣题目代码工程C实现python实现 力扣题目 一个整数 num 的 k 美丽值定义为 num 中符合以下条件的 子字符串 数目: 子字符串长度为 k 。 子字符串能整除 num 。 给你整数 num 和 k ,请你返回 num 的 k 美丽值。 注意: 允许有 前…...
一个在C#中集成Python的例子
一个在C#中集成Python的例子。在C#中可以执行Python脚本,在Python中也可以调用C#宿主中的功能(clr.AddReference(Business))。 文件说明 Debug为执行目录 Mgr.exe为执行文件 Py\init.py为python初始化脚本 Py\Lib.zip为python需要的模块&…...
基于RandLA-Net深度学习模型的激光点云语义分割
一、场景要素语义分割部分的文献阅读笔记 RandLA-Net是一种高效、轻量级的神经网络,其可直接逐点推理大规模点云的语义标签。RandLA-Net基于随机点采样获得了显著的计算和内存效率,并采用新的局部特征聚合模块有效地保留了几何细节,弥补了随机…...
C语言的结构体与联合体
引言 C语言提供了结构体和联合体两种聚合数据类型,使得程序员可以创建包括多个数据类型的复杂数据结构。结构体用于将不同类型的数据组合成一个单元,而联合体用于在同一存储空间中存储不同类型的数据。本篇文章将详细介绍C语言中的结构体和联合体&#x…...
React Hooks小记(三)_forwardRef
forwardRef 【写在前面】 1、ref 的作用是获取实例,但由于函数组件不存在实例,因此无法通过 ref 获取函数组件的实例引用,而 React.forwardRef 就是用来解决这个问题的。 2、React.forwardRef 会创建一个 React 组件,这个组…...
面试复习记录
六级终于结束了,之前背的八股几乎也忘得差不多了,今天开始继续准备秋招,以下是每天的安排,会按时更新,就当是一种对自己的督促,也欢迎小伙伴们一起来互相监督。 2024.6.16 力扣:sql基础题库50…...
块级元素与行内元素详解
在网页设计与开发中,元素根据其在页面布局中的表现可分为两大类:块级元素(Block-level Elements)和行内元素(Inline Elements)。理解它们的特性和使用规则对于构建结构清晰、布局合理的网页至关重要。 块级…...
Kotlin编程实践-【Java如何调用Kotlin中带默认值参数的函数】
问题 如果你有一个带有默认参数值的 Kotlin 函数,如何从 Java 调用它而无须为每个参数显式指定值? 方案 为函数添加注解JvmOverloads。 也就是为Java添加重载方法,这样Java调用Kotlin的方法时就不用传递全部的参数了。 示例 在 Kotlin …...
中国城市统计年鉴(1985-2023年)
数据年限:1985-2023 数据格式:pdf、excel 数据内容:共分四个部分 第一部分是全国城市行政区划,列有不同区域、不同级别的城市分布情况; 第二、三部分分别是地级以上城市统计资料和县级城市统计资料,具体包括…...
RestTemplate远程请求的艺术
1 简说 编程是一门艺术,追求优雅的代码就像追求优美的音乐。 很多有多年工作经验的开发者,在使用RestTemplate之前常常使用HttpClient,然而接触了RestTemplate之后,却愿意放弃多年相处的“老朋友”,转向RestTemplate。那么一定是RestTemplate有它的魅力,有它的艺术风范。…...
Spring 整合 MyBatis 底层源码解析
大家好,我是柳岸花开。今天我们要讲的是 Spring 整合 MyBatis 的底层源码解析。希望大家能更深入理解 Spring 和 MyBatis 的整合原理,并应用到实际项目中。 由很多框架都需要和Spring进行整合,而整合的核心思想就是把其他框架所产生的对象放到…...
LeetCode 189.轮转数组
1.这个题我用的方法比较巧妙,大家如果觉得好的话,就给个免费的赞吧^ _ ^,谢谢了。 void reverse(int* nums,int left,int right) {while(left < right){int a nums[left];nums[left] nums[right];nums[right] a;left;right--;} } void rotate(int…...
JDK17 你的下一个白月光
JDK版本升级的非常快,现在已经到JDK20了。JDK版本虽多,但应用最广泛的还得是JDK8,正所谓“他发任他发,我用Java8”。 但实际情况却不是这样,越来越多的java工程师拥抱 JDK17,于是了解了一下 JDK17新语法&a…...
springboot优雅shutdown时如何保障异步线程的安全
我前面写了一篇springboot优雅shutdown的文章,看起来一切很美好。 https://blog.csdn.net/chenshm/article/details/139640775 那是因为没有进行多线程测试。如果一个请求中包括阻塞线程(主线程)和非阻塞线程(异步线程)…...
C++格式化库fmt使用方法
1. 格式化库fmt简介 fmt github地址 api说明 格式化参数说明 内容的格式化,体现在代码中主要表现为字符串、基本类型、自定义类型的拼接。例如说打印日志、拼接变量等。C中我们会经常使用类似printf,snprintf(C风格使用不方便),std::string.append(繁琐), std::io…...
网站通栏是什么/网站开发北京公司
主要分为三个步骤 应用程序处理(简而言之就shader编码中可以处理的一切信息都属与应用程序处理阶段)>几何顶点处理(主要工作坐标的顶点变换)>光栅化处理(与像素处理相关操作) 关于渲染管线 原文链接 http://game.ceeger.com/forum/read.php?tid10970&fid2 正文所谓…...
凡科轻站官网/地推接单在哪个平台找
shell脚本执行报错exec format error,脚本权限没有问题: 原因可能是脚本里#!/bin/bash和#!/bin/sh兼容问题导致,标准系统支持的都是/bin/bash; 首先查看当前系统的bash或dash: [rootlocalhost ~]# ls -l …...
做公司网站写什么信息/我想做网络推广
oracle的架构大概分为3部分, 客户端:用户端 oracle instance:叫做实例,由内存结构(内存池或者叫SGA)和后台进程组成。Oracle Instance是Oracle RDBMS的核心之一,负责RDBMS的管理功能。内存结构有…...
建设一个网站需要提供什么手续/优化的意思
su – username 详细请看: Linux 系统下用户之间的切换_北斗小鱼-CSDN博客_linux 切换用户...
全包家装原创装修网站/怎么做百度网页
美食节 题解:学习了动态加边,可以说是进一步理解了网络流。具体思路就是考虑每一道菜,如果这是该位厨师最后一次做,那么等待时间就是做这道菜的时间,如果是倒数第二次做,就要两倍时间(目前做了一…...
免费咨询律师24小时/佛山seo技术
php向数组中增加数据的方法是什么2020-06-30 04:48:23php向数组中增加数据的方法是什么?使用函数array_pusharray_push() 函数向第一个参数的数组尾部添加一个或多个元素(入栈),然后返回新数组的长度。该函数等于多次调用 $array[] $value。语法; array_push(arr…...