嵌入式系统复习--基于ARM的嵌入式程序设计
文章目录
- 上一篇
- 编译环境
- ADS编译环境下的伪操作
- GNU编译环境下的伪操作
- ARM汇编语言的伪指令
- 汇编语言程序设计
- 相关运算操作符
- 汇编语言格式
- 汇编语言程序重点
- C语言的一些技巧
- 下一篇
上一篇
嵌入式系统复习–Thumb指令集
编译环境
ADS/SDT IDE开发环境:它由ARM公司开发,使用了CodeWarrior公司的编译器
一般的:集成了GNU开发工具的IDE开发环境:它由GNU的汇编器as、交叉编译器gcc、和链接器ld等组成
- 伪操作:ARM汇编语言程序里的特殊指令助记符,主要作用是完成汇编程序各种准备工作,在源程序进行编译时由汇编程序处理,而不是在计算机运行期间执行
- 宏指令:是一段独立的代码、可插在源程序中,它通过伪操作来定义。通过实际指令替代宏体实现相关的一段代码
- 伪指令:ARM汇编语言里的特殊指令助记符,不在处理器运行期间由机器执行。它们在编译时将被合适的机器指令替代
ADS编译环境下的伪操作
常用伪操作可分为:
- 符号定义伪操作
-
定义全局变量
伪操作 语法格式 作用 GBLA GBLA Variable 声明一个全局的算术变量,初始化为0 GBLL GBLL Variable 声明一个全局的逻辑变量,初始化为false GBLS GBLS Variable 声明一个全局字符串变量,初始化为空串 -
定义局部变量
伪操作 语法格式 作用 LCLA LCLA Variable 声明一个局部的算术变量,初始化为0 LCLL LCLL Variable 声明一个局部的逻辑变量,初始化为false LCLS LCLS Variable 声明一个局部字符串变量,初始化为空串 -
为变量赋值
伪操作 语法格式 作用 SETA Variable SETA expr 给一个算术变量赋值 SETL Variable SETL expr 给一个逻辑变量赋值 SETS Variable SETS expr 给一个字符串赋值 -
给一串寄存器命名
伪操作 语法格式 作用 RLIST name RLIST {list of registers} 为一个通用寄存器列表定义名称
-
- 数据定义伪操作
- 为一个变量分配内存地址
伪操作 语法格式 作用 DCB {label} DCB expr 分配一段 字节
的内存单元,用字节的方式放exprDCD {label} DCD expr 分配一段 字
的内存单元,用字的方式放expr - 定义数据块的起始地址
伪操作 语法格式 作用 LTORG LTORG 声明一个数据缓冲池的开始(说明此指令后面不是代码,而是数据了)
- 为一个变量分配内存地址
- 汇编控制伪操作
- 条件
IF 逻辑表达式 { ELSE } ENDIF
- 循环
WHILE 逻辑表达式 ... WEND
- 宏定义
类似子程序调用,但是他不是跳转到子程序,而是直接将宏定义的代码,直接复制到宏名称那里MACRO {$label} macroname {$parameter} MEND
- 条件
- 信息报告伪操作
在程序运行不同阶段可以设置让他弹出信息伪操作 语法格式 作用 OPT OPT n 通过OPT可以在源程序中设置列表选项 - 其他伪操作
- 告诉编译器要选择的指令
伪操作 语法格式 作用 CODE 16 CODE 16 告诉编译器后面是Thumb指令 CODE 32 CODE 32 告诉编译器后面是ARM指令 - 定义常量(给变量或标号赋值)
伪操作 语法格式 作用 EQU name EQU expr 将name赋值为expr - 程序结构指令
伪操作 语法格式 作用 AREA AREA sectioname {, attr} 定义一个代码段或数据段 ENTRY ENTRY 指定程序的入口点 END END 告诉编译器已经到了源程序结尾 - 混合调用用到的指令
伪操作 语法格式 作用 EXPORT/GLOBAL EXPORT symbol {[WEAK]} 声明一个文件可以被其他文件引用,相当于声明以个全局变量 IMPORT/EXTERN IMPORT/EXTERN symbol {[WEAK]} 告诉编译器当前符号不是在本源文件中定义的,而是在其他文件中,而在本文件中可能使用
- 告诉编译器要选择的指令
GNU编译环境下的伪操作
常用伪操作为:
-
常量编译控制伪操作
伪操作 语法格式 作用 .byte .byte expr 分配一段字节空间,并用字节的方式放入expr .hword/ .short .hword expr 分配一段半字节空间,并用半字的方式放入expr .ascii .ascii expr 定义字符串expr(非零结束符) .asciz/.string .asciz 定义字符串(以 /0
为结束符).word .word expr 分配一段字内存空间 -
汇编程序代码控制伪操作
伪操作 语法格式 作用 .section .section expr 定义域中包含的段 .text .text{subsection} 代码 .data .data {subsection} 数据 .code 16 .code 16 表明后面是Thumb指令集 .code 32 .code 32 表明后面是ARM指令集 .end .end 结束标识符 .include .include “filename” 将一个源文件包含到当前源文件中 -
宏及条件编译控制伪操作
.macro以及.endm
.macro condition .endm
.ifdef, .else及.endif
.ifdef condition .else .endif
-
其他伪操作
伪操作 语法格式 作用 .print .print string 打印信息到标准输出
ARM汇编语言的伪指令
伪操作 | 语法格式 | 作用 |
---|---|---|
ADR | ADR {cond} register, expr | 将基于PC或基址寄存器的地址读到寄存器中,小范围的地址读取 |
ADRL | ADRL {cond} register,expr | 将基于PC或基址寄存器的地址读到寄存器中,中等范围的地址读取 |
LDR | LDR {cond} register | 将一个32位的立即数或一个地址值读取到寄存器中,大范围地址读取 |
NOP | NOP | 汇编是替换成ARM的空指令(占用一个操作时间但什么到不做) |
汇编语言程序设计
-
文件格式
ARM源程序文件可以有任意一种纯文本
文件编写程序代码
文件格式对应与源程序文件 文件名 说明 汇编程序文件 *.S 用ARM汇编语言编写的ARM程序或Thumb程序 C程序文件 *.C 用C语言编写的程序代码 头文件 *.H 通常将常量命名、宏定义、数据结构定义等放在头文件中 -
ARM汇编语言语句格式如下:
{符号} {指令 | 伪操作 | 伪指令} {; 注释}
;为注释符
-
符号可以代表地址、变量和数字常量
命名规则:符号由大小写字母、数字以及下划线组成(区分大小写)
局部标号以数字开头,其他符号都不能以数字开头 -
变量: 三种变量:数字变量、逻辑变量、串变量
-
数字常量:表示方式:十进制,十六进制,n进制
-
标号:表示程序中的指令或地址的标号,分为基于PC的标号、基于寄存器的标号、绝对地址
-
局部标号:相对当前位置
% {F|B} {A|T} N{routname}
其中:%表示引用操作、F表示只先向前搜索、B表示向后搜索、A表示编译器搜索宏的搜索嵌套层次、T表示宏的当前层次
-
相关运算操作符
- 字符串表达式相关操作符
-
LEN:返回字符串的长度
例:GBLS STR STR SETS "AAA" :LEN: STR ;LEN = 3
-
CHR: 返回一个字符的ASCII值
:CHR:A
-
STR: 将对应变量(数字量或逻辑量)的表示形式用字符串的形式表示
例:GBLA A1 A1 SETA 15 :STR: A1
-
LEFT :返回一个字符从最左端的一定长度的字串
格式:A :LEFT: B
A为源字符串;B为数字量,表示返回字符个数
例:GBLS STR1 GBLS STR2 SETS STR1 "AAAABBBB" SETS STR2 STR1 :LEFT:3 ;结果为STR2为 “AAA”
RIGHT同理,返回最右端一定长度的字串
-
CC:连接2个字符串
A :CC: B
A为第一个源字符串;B为第二个源字符串
例:GBLS STR1 GBLS STR2 STR1 SETS "AAACCC" STR2 SETS "BBB" :CC: (STR1 :LEFT: 3) ; 结果为STR2 为"BBBAAA"
-
- 数字表达式相关操作符
- NOT:按位取反
:NOT: A
- +、-、x、/及MOD: 算术操作符
A + B ; A - B; A x B; A / B; A :MOD: B;
- ROL、ROR、SHL、SHR:循环移位操作
A :ROL: B ;将整数A循环左移B位 A :ROR: B;将整数A循环右移B位 A :SHL: B ;将整数A左移B位空位补0 A :SHR: B;将整数A右移B位空位补0
- AND、OR、EOR:按位逻辑操作符
A :AND: B ;按位与操作 A :OR: B;按位或操作 A :EOR: B;按位异或操作
- NOT:按位取反
- 逻辑表达式
- 关系操作符
=、>、<、
不等于 /= 或则 <> - 逻辑操作符
:LNOT: ;A 取反 A :LAND: B;逻辑与 A :LOR: B;逻辑或 A :LEOR: B;逻辑异或
- 关系操作符
汇编语言格式
ARM汇编语言是以段(section)为单位来组织源文件的。
段是相对独立的、具有特定名称的、不可分割的指令或者数据序列。
段又可以分为代码段和数据段。一个源程序至少需要一个代码段。
例:
AREA EXAMPLE(段的名字), CODE(代码段), READONLY(只读)
ENTRY(程序入口点)
start
...
END
汇编语言程序重点
-
子程序的调用
子程序的调用通过BL指令来完成
语法格式为BL subname(被调用子程序的名称)
-
子程序的返回
在返回调用子程序时,将LR寄存器(R14)中的值拷贝回程序寄存器(R15)
当没有嵌套时SUB2 ...MOV PC, R14
当发生嵌套时, 对于在子程序中出现嵌套调用时,链接寄存器LR中的返回地址可能会在第二次调用时被覆盖,所以需要将返回地址压入堆栈来进行保存
SUB1 STMFD SP!, {R0 - R7, R14}; 保存工作寄存器和链接 BL SUB2 ... LDMFD SP!, {R0 - R7, PC}; 恢复工作寄存器并返回
-
跳转表
类似于c++中的switch
调用一系列子程序中的一个,而决定调用哪一个由程序的计算值决定。
例:BL JUMPTAB; R0存放对应的跳转信息 0表示0号程序...JUMPTAB ADR R1, SUBTAB; R1 <- SUBTABCMP R0, #SUBMAX; 检查是否超限LDRLS PC, [R1, R0, LSL #2]; 如果OK则跳转到表中B ERROR; 否则发生错误SUBTAB DCD SUB0DCD SUB1DCD SUB2... SUB MAX;散转表结束地址
-
ARM与Thumb间的状态转换
状态切换是通过一条专用的转移交换指令BX来实现的。
当Rn寄存器中的目的地址的最后一位为0时转换到ARM状态
当Rn寄存器中最后一位为1时,转换到Thumb状态
Thumb地址是半字对齐的末尾一定是0
CODE32ADR R0, Into_Thumb + 1BX R0... CODE16Into_Thumb:...ADR R5, BACK_TO_ARMBX R5... CODE32Back_to_ARM...
应用实例:
- 简单的ARM指令程序
- 数据块复制
AREA STRINGCOPY, CODE, READ ONLY
NUM EQU 20
CODE 32
ENTRY
startLDR R0, =srcLDR R1, =dst LDR R2, #NUM; 移动字符串个数LDR SP, #0x400 ; 初始化堆栈指针
BACK; 备份STMFD SP!, {R4-R11}; 将R4与R11中的内容提前保护MOVS R3, R2, LSR #3; 移动次数NUM整除8的商BEQ YUSHU; 如果不满8个字符,看是否有余数
BLOCKCOPY ; 按块移动每次移动8个字符LDMIA R0!, {R4-R11} ;将src中8个字符块移动到R4到R11中STMIA R1!, {R4-R11} ;将移入的字符移到dst中SUBS R3, R3, #1BNE BLOCKCOPY; 未把商移动完就循环LDMFD SP!, {R4-R11}; 将保护的寄存器出栈
YUSHUANDS R2, R2, #7; 将R2只保留8以内的余数了,方便后边一个字符的搬运BEQ stop
WCOPY ; 一个字符一个字符的移动LDR R3, [R0], #4; 字对齐每次移动4STR R3, [R1], #4SUBS R2, R2, #1BNE WCOPY
stopMOV R0, #0x18LDR R1, #0x20026SWI 0x123456
AREA DATA1, DATE, READWRITE
src DCD 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4
dst DCD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
END
- 利用跳转表实现程序跳转
C语言的一些技巧
-
变量定义
- 把所有相同类型的变量放在一起定义,这样可以优化存储器空间
- 局部变量使用32位int或unsinged int有时会更有效率。因为每个寄存器是32位的
- 变量定义为了精简是要避免使用冗余变量。但有时使用冗余变量可以减少存储器的访问次数,提高系统性能,冗余变量一般在寄存器,一般变量在存储器
-
参数传递
为了单独编译C语言程序和汇编程序能够相互调用,定义了同一的函数过程调用标准ATPCS
ATPCS规则:- 寄存器的使用规则
子程序通过寄存器R0 ~ R3来传递参数, 使用R4 ~ R11来保存局部变量,因此在进入子程序前要保存这些寄存器的值,返回后恢复,在Thumb中,只使用R4 ~ R7 - 数据栈的使用规则
ATPCS规定数据栈为FD(满递减)类型,并且对数据栈的操作时8字节对齐的 - 参数的传递规则
当参数固定的情况下,第一个整数参数通过寄存器R0 ~ R3来传递。其他参数通过数据栈传递
当参数个数可变的子程序:当不超过4个时用R0 ~ R3 来传递,超过4个时,使用数据栈来传递参数
结果返回是以32位为界,每多一个32就从R0 ~ R3中多增加一个来传递
- 寄存器的使用规则
-
循环时使用
i --
可以省一些汇编指令,更有效率
下一篇
未完待续
相关文章:

嵌入式系统复习--基于ARM的嵌入式程序设计
文章目录 上一篇编译环境ADS编译环境下的伪操作GNU编译环境下的伪操作ARM汇编语言的伪指令 汇编语言程序设计相关运算操作符汇编语言格式汇编语言程序重点C语言的一些技巧 下一篇 上一篇 嵌入式系统复习–Thumb指令集 编译环境 ADS/SDT IDE开发环境:它由ARM公司开…...

【C++入门到精通】异常 | 异常的使用 | 自定义异常体系 [ C++入门 ]
阅读导航 引言一、C异常的概念二、异常的使用1. 异常的抛出和捕获(1)throw(2)try-catch(3)catch(. . .)(4)异常的抛出和匹配原则(5)在函数调用链中异常栈展开…...

NX二次开发 Block UI 指定方位控件的应用
一、概述 NX二次开发中一般都是多个控件的组合,这里我首先对指定方位控件进行说明并结合选择对象控件,具体如下图所示。 二、实现功能获取方位其在选择面上原点的目标 2.1 在initialize_cb()函数中进行初始化,实现对象选择过滤面 //过滤平…...

2024年【R2移动式压力容器充装】模拟考试及R2移动式压力容器充装实操考试视频
题库来源:安全生产模拟考试一点通公众号小程序 2024年【R2移动式压力容器充装】模拟考试及R2移动式压力容器充装实操考试视频,包含R2移动式压力容器充装模拟考试答案和解析及R2移动式压力容器充装实操考试视频练习。安全生产模拟考试一点通结合国家R2移…...
数仓工具—Hive进阶之StorageHandler(23)
Storage Handler 引入Storage Handler,Hive用户使用SQL的方式读写外部数据源, 例如ElasticSearch、 Kafka、HBase等数据源的查询对非专业开发是有一定门槛的,借助Storage Handler,他们有了一种方便快捷的手段查询数据,Storage Handler作为Hive的存储插件,我们需要的时候直…...
科技创新创业
科技创新创业是一个涉及多个方面的过程,主要包括以下几个方面: 创意产生:创业的起始点通常是一个新的创意或想法,这可能是一个新的产品、服务或技术的概念。这个创意需要独特且具有商业潜力。市场调研:一旦有了创意&a…...

高校电力能耗监测精细化管理系统,提升能源利用效率的利器
电力是高校不可离开的重要能源,为学校相关管理人员提供在线用能查询统计等服务。通过对学校照明用电、空调用电等数据的采集、监控、分析,为学校电能管理制定合理的能源政策提供参考。同时,也可以培养学生的节能意识,学校后勤电力…...

Java_Swing程序设计
swing组件允许编程人员在跨平台时指定统一的外观和风格。 Swing组件通常被称为轻量级组件, JFrame在程序中的语法格式: JFrame jfnew JFrame(title); Container containerjf.getContentPane(); jf:JFrame类的对象 container:Container类的对象。 J…...

ZeroBind:DTI零样本预测器
现有的药物-靶点相互作用(DTI)预测方法通常无法很好地推广到新的(unseen)蛋白质和药物。 在这项研究中,作者提出了一种具有子图匹配功能的蛋白质特异性元学习框架 ZeroBind,用于根据其结构预测蛋白质-药物相…...

Win10子系统Ubuntu实战(一)
在 Windows 10 中安装 Ubuntu 子系统(Windows Subsystem for Linux,简称 WSL)有几个主要的用途和好处:Linux 环境的支持、跨平台开发、命令行工具、测试和验证、教育用途。总体而言,WSL 提供了一种将 Windows 和 Linux…...
[足式机器人]Part3 机构运动学与动力学分析与建模 Ch00-2(3) 质量刚体的在坐标系下运动
本文仅供学习使用,总结很多本现有讲述运动学或动力学书籍后的总结,从矢量的角度进行分析,方法比较传统,但更易理解,并且现有的看似抽象方法,两者本质上并无不同。 2024年底本人学位论文发表后方可摘抄 若有…...

云计算历年题整理
目录 第一大题 第一大题HA计算 给出计算连接到EC2节点的EBS的高可用性(HA)的数学公式,如场景中所述;计算EC2节点上的EBS的高可用性(HA);场景中80%的AWS EC2节点用于并行处理,总共有100个虚拟中央处理单元(vCPUs)用于处理数据&a…...
2401vim,vim重要修改更新大全
原文 2023 更好的UTF-16支持 添加strutf16len()和utf16idx(),并在byteidx(),byteidxcomp()和charidx()中添加utf16标志,在内置.txt文档中. 添加crypymethod xchacha20v2 与xchacha20基本相同,但更能抵御libsodium的变化. 2022 添加"smoothscroll" 用鼠标滚动…...
安卓多用户管理之Userinfo
目录 前言Userinfo----用户信息1.1 属性1.2 构造器1.3 信息的判断及获取方法1.3.1 获取默认用户类型1.3.2 基础信息判断 1.4 序列化部分 总结 前言 UserManagerService内部类UserData中有一个Userinfo类型的info参数,在UserData中并未有所体现,但在后续…...
JavaScript-流程控制-笔记
1.流程语句的分类 顺序结构 分支结构 循环结构 2.if语句 1)if结构 if( 条件 ){ // 条件成立执行的代码 } 2)if else 结构 if( 条件 ){ // 条件成立执行的代码 }else{ // 条件不成…...

springboot + vue3实现增删改查分页操作
springboot vue3实现增删改查分页操作 环境最终实现效果实现功能主要框架代码实现数据库后端前端 注意事项 环境 jdk17 vue3 最终实现效果 实现功能 添加用户,禁用,启用,删除,编辑,分页查询 主要框架 后端 spri…...
leetcode01-重复的子字符串
题目链接:459. 重复的子字符串 - 力扣(LeetCode) 一般思路: 如果存在k是S的字串,记k的长度为s,S的长度为n,则一定有n是s的倍数,且满足对于j∈[s,n],一定存在s[j]s[j-s]; …...

目标检测数据集 - 夜间行人检测数据集下载「包含VOC、COCO、YOLO三种格式」
数据集介绍:夜间、低光行人检测数据集,真实场景高质量图片数据,涉及场景丰富,比如夜间街景行人、夜间道路行人、夜间遮挡行人、夜间严重遮挡行人数据;适用实际项目应用:公共场所监控场景下夜间行人检测项目…...

【YOLO系列】 YOLOv4思想详解
前言 以下内容仅为个人在学习人工智能中所记录的笔记,先将目标识别算法yolo系列的整理出来分享给大家,供大家学习参考。 本文未对论文逐句逐段翻译,而是阅读全文后,总结出的YOLO V4论文的思路与实现路径。 若文中内容有误…...

查询json数组
步骤一:创建表格 首先,我们需要创建一个表格来存储包含JSON对象数组的数据。可以使用以下代码创建一个名为 my_table 的表格: CREATE TABLE my_table (id INT PRIMARY KEY AUTO_INCREMENT,json_data JSON ); 上述代码创建了一个包含两个列的…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...