ARM简单程序设计【嵌入式系统】

news2025/1/19 17:24:11

ARM简单程序设计【嵌入式系统】

  • 前言
  • 推荐
  • ARM简单程序设计
    • 创建项目
    • 注意事项
    • 顺序结构程序
      • 两数之和
    • 分支结构程序
      • 符号函数
    • 循环结构程序
      • 已知循环次数
      • 未知循环次数
    • 两重循环
      • 冒泡排序
    • 子程序设计
      • ①寄存器传递参数方式
      • ②存储区域传递参数方式
      • ③ 堆栈传递参数方式
  • 最后

前言

2023-4-6 20:26:54

以下内容源自《【嵌入式系统】》
仅供学习交流使用

推荐

Keil 4 安装教程及简单使用【嵌入式系统】

ARM简单程序设计

创建项目

新建工程xxx

芯片:ARM7 (Little Endian)

在这里插入图片描述

设置工程属性
在这里插入图片描述

在这里插入图片描述

Build结果必须是0Error的
在这里插入图片描述
如果是下图看配置是否正确
在这里插入图片描述

注意这个:
在这里插入图片描述

注意事项

1.每一次修改代码就需要重写Build

2.READWRITE区变量初始化为0的解决

格式:

	AREA  xxx, CODE, READONLY	; 代码段的名字 symbol
	ENTRY                   			; 程序的入口
	CODE32
start
	xxx
stop				  
	
	MOV	R0,   #0x18	
	LDR	R1,  =0x20026
	SWI	0x123456
	
    AREA  Data0, DATA, READONLY	;放到READONLY	注意段名字和下面不一样 Data0 Data
x	DCD		-25	

    AREA  Data, DATA, READWRITE
y	DCD		0
    	END 

顺序结构程序

两数之和

ARMex.s

例4- 1试编制一程序,完成10+3的操作


	AREA  ARMex, CODE, READONLY	; 代码段名ARMex
	ENTRY					; 程序的入口
	CODE 32
start
	MOV	R0,	#10		; 将立即数10存入寄存器R0
	MOV	R1,	#3		; 将立即数3存入寄存器R1
	ADD	R0,	R0,	R1	; R0 = R0 + R1
stop
	MOV	R0,	#0x18		; 这三条指令是ADS调试环境特约
	LDR	R1,	=0x20026	;程序运行结束返回编译器调试环境
	SWI		0x123456

	END				; 结束 

结果如下

(R0)=13
在这里插入图片描述

分支结构程序

符号函数

例4-2给定以下符号函数:

		{	1 		x>0
y=    	{	0 		x=0
	    {	-1 	x<0

任意给定值,假定为-25,存放在x单元,函数值存放在y单元;要求根据x中的值来确定y的值。

symbol.s

	AREA  symbol, CODE, READONLY	; 代码段的名字 symbol
	ENTRY                   			; 程序的入口
	CODE32
start
	LDR     R0,  =x		; 加载数据段中的变量x地址,存入R0
	LDR     R1,  =y		; 加载数据段中的变量y地址,存入R1
	LDR		R2,  [R0]	; 加载变量x的值,存入R2
compare
	CMP	R2,  #0		; 将R2的值与0作比较
	BEQ	ZERO		; 如果R2等于0,那么转向标号ZERO处
	BGT	PLUS		; 如果R2大于0,那么转向标号PLUS处 
	MOV	R3,  #-1		; 否则,R2小于0,将-1存入R3中
	B	stop
ZERO
	MOV	R3,  #0		; R2等于0,将0存入R3中
	B	stop
PLUS
	MOV	R3,  #1		; R2大于0,将1存入R3中
	


stop				
    STR	R3,[R1]
	
	MOV	R0,   #0x18	
	LDR	R1,   =0x20026
	SWI	0x123456
	
    AREA  Data0, DATA, READONLY   
x	DCD		-25	

    AREA  Data, DATA, READWRITE
y	DCD		0
    END 

结果如下

R0=&x=0x00000048
R1=&y=0x40000000
R2=x=-25
R3=y=-1
在这里插入图片描述

循环结构程序

已知循环次数

例 4‑4 从x单元开始的30个连续字单元中存放有30个无符号数,从中找出最大者送入y单元中。
分析:
根据题意,把第一个数先送入Rx寄存器,将Rx中的数与后面的29个数逐个进行比较,如果Rx中的数较小,则将该较大的数送入Rx ;继续与余下的数据逐个比较。在比较过程中, Rx中始终保持较大的数,共计比较29次,则最终Rx中保留了最大数,最后把Rx中的数(最大者)送入y单元。

max.s

	AREA  max, CODE, READONLY		; 代码段的名字 max
	ENTRY                   			; 程序的入口
	CODE32
num	EQU	29                   ; 比较的次数
start
	LDR	R0,  =x           ; R0指向源数据块x
	LDR	R1,  =y           ; R1指向单元y
	LDR	R2,  =num      ; R2作为计数器
	LDR	R3,  [R0]        ; 将源数据块x中第一个数加载到R3中
compare
	ADD	R0, R0,	#4    ; 每进行一次比较,将R0指针地址加4
	LDR	R4, [R0],#4       ; 依次将源数据块x中下一个数加载到R4中
	CMP	R3, R4             ; 比较R3和R4中数的大小 
	MOVCC  R3,  R4          ; 如果R3小于R4,则将较大的数送入R3中
	SUBS	R2,  R2,  #1       ; 计数器值减1
	BNE	compare           ; 如果不为0,那么继续跳到compare执行
	STREQ	R3,  [R1]          ; 如果为0,那么循环比较结束,R3是最大的数
			       ; 并且将R3中的数加载到R1指向的单元(即y)中 

stop
	MOV	r0, #0x18
	LDR	r1, =0x20026		
	SWI	0x123456        

	AREA  Data0, DATA, READONLY
x	DCD	73,59,61,34,81,107,225,231,54,43
	DCD	100,35,1,42,222,254,34,71,100,31
	DCD	33,119,13,44,18,147,55,244,97,3

	AREA  Data, DATA, READWRITE

y	DCD	0
	END

说明

结果如下

R0=&x
R1=&y=0x40000000
R3=0x000000FE=254
在这里插入图片描述

未知循环次数

例 4‑5 从自然数1开始累加,直到累加和大于1000为止,统计被累加的自然数的个数,并把统计的个数送入n单元,把累加和送入sum单元。
分析:
根据题意,被累加的自然数的个数事先未知,因此不能用计数方法控制循环。但题目中给定一个条件,即累加和大于1000则停止累加,因此,可以根据这一条件控制循环。我们用R3寄存器放累加和,用R4寄存器放每次取得的自然数,其中它的值也是统计自然数的个数。

SUM.s

     AREA  SUM, CODE, READONLY	; 代码段的名字 SUM
     ENTRY                   			; 程序的入口
     CODE32
start
     LDR   R0,   =n            ; 将数据段中自然数的个数n的地址加载到R0寄存器
     LDR   R1,   =sum       ; 将数据段中自然数的累加和sum的地址加载到R1寄存器
     LDR   R3,   =0            ; R3存放自然数的累加和
     LDR   R4,   =0            ; R4用于循环个数的统计/每次取得的自然数
     LDR   R5,   =1000      ; R5用于循环结束的界限值
continue
     ADD	R4,   R4,	    #1    ; 取下一个自然数
     ADD	R3,   R3,	   R4    ; 累加自然数
     CMP	R3,   R5             ; 比较累加和是否超过了1000
     BCC	continue            ; 如果小于1000,那么跳到compare执行
     STRCS   R3,  [R1]     ; 如果大于1000,那么将累加和存储到R1所指向的单元中
     STRCS   R4,   [R0]    ; 如果大于1000,那么将已累加的自然数个数值存储
		            ; 到R0所指向的单元中 

stop
        MOV    r0, #0x18
        LDR     r1, =0x20026			
        SWI     0x123456 
     		
        AREA  Data, DATA, READWRITE
n	DCD	0	    ; 定义累加的自然数的个数
sum	DCD	0 	   ; 定义自然数的累加和

        END

结果如下

R0=&n=0x40000000
R1=&sum=0x40000004
R3=0x000004DB=1035
R4=0x0000002D=45
R5=0x000003E8=1000

在这里插入图片描述

两重循环

冒泡排序

Bibble.s

	AREA Bibble, CODE, READONLY
	ENTRY
start

	;想实现数组拷贝 需要输入原数组 数组长度 输出目的数组 即可
	;这里借用字符串拷贝 要求源数组最后加一个无效元素0 中间不能出现0
    LDR       R1,    =src0        	; R1指向数据区的源字符串
    LDR       R0,    =src        	; R0指向数据区的目的字符串
    BL          strcopy             ; 调用子程序strcopy,完成字符串拷贝


	LDR	R1,=src				; (右指针)R1起初指向src第一个单元	
	MOV	R2,  #0				; 用于外层循环控制计数器,并初始化为0
	LDR	R4,  num         	; R4中是数据区中待排序数据个数
	SUB	R4,  R4,  #1		;
	ADD	R1,  R4,LSL #2			;(右指针)R1指向src最后一个单元 R1=R1+R4*4,
outer						; 外层循环
	LDR	R0,  =src				;(左指针)R0指向数据区src单元
inner						; 内层循环
	LDR	R5,  [R0]				; 将R0所指向单元的数加载到R5中
	LDR	R6,[R0, #4]				; 将相邻单元的数加载到R6中
	CMP	R5,  R6     			; 比较相邻两单元中的数
	STRGT  R6,  [R0]  			;如果前者大于后者,那么两个数交换
	STRGT  R5, [R0, #4]  	    ; 内层循环修改、控制部分
	ADD	R0,  R0,  #4  			; 地址指针向下拨移4个字节
	CMP	R0,  R1   				; 是否扫描了一遍
	BNE	inner 					; 没有完成一遍,继续内循环
							; 外层循环修改、控制部分,表示已经完成了一遍,
	ADD	R2,  R2,  #1		; 外层循环控制计数器加1
	SUB	R1,  R1,  #4		; 右指针R1向左指针方向移动4字节
	CMP	R2,  R4				; 是否全部扫描	
	BNE	outer				; 没有完成全部扫描,继续外循环
stop
	MOV R0,  #0x18  		; 程序结束返回编译器调试环境
	LDR		R1,  =0x20026
	SWI		0x123456
	
strcopy 
    LDR     R2,     [R1],    #4    ; 将R1指向的单元内容加载到R2中
    STR     R2,     [R0],    #4    ; 将R2中的数存储到R0指向的单元中
    CMP     R2,      #0            ; 检查R0的值是否等于0
    BNE     strcopy                ; 如果不等于0,那么转到strcopy处执行 
    MOV     PC,    LR              ; 子程序返回 
        	
	AREA BlockData0, DATA, READONLY
src0 DCD	18,4,2,35,3,20,1,23,12,21,0		
num	DCD	10
	AREA BlockData, DATA, READWRITE
src	DCD	18,4,2,35,3,20,1,23,12,21,0   ;Keil会把此数组初始化为0

	END

说明
因为待排序数组直接放到READWITER,会有初始化为0的问题
所以就需把其放到READONLY下
但是,这就排不了序了
所以需要把其拷贝到一个READWITER下的数组,对其进行排序
这里我借用了字符串拷贝
真正的数组拷贝的设计:需要输入原数组 数组长度 输出目的数组 即可

另外
右指针的初始化

; (右指针)R1起初指向src第一个单元	 
LDR	R1,=src			; 0x40000000
; R4中是数据区中待排序数据个数
LDR	R4,  num         ;10
SUB	R4,  R4,  #1		;9
;(右指针)R1指向src最后一个单元 R1=R1+R4*4,用左移两位实现 一个元素占4个字节
ADD	R1,  R4,LSL #2		;0x400000000+9*4=0x40000032

结果如下

1.完成数组拷贝

末尾的0是无效的
在这里插入图片描述

2.完成初始化
R0左指针->第一个
R1右指针->倒数的一个
在这里插入图片描述

3.第一遍循环
R0左指针->第一个
R1右指针->倒数的二个
倒数第一个,为最大的树
在这里插入图片描述
4.最终结果
R0左指针
R1右指针
R2=9 循环次数
R4=9 循环次数
R5,R6 是最后交换的两个数
在这里插入图片描述

子程序设计

①寄存器传递参数方式

StrCopy.s

 AREA    StrCopy, CODE, READONLY
        ENTRY
        CODE32
start
        LDR       R1,    =srcstr        ; R1指向数据区的源字符串
        LDR       R0,    =dststr        ; R0指向数据区的目的字符串
        BL          strcopy                 ; 调用子程序strcopy,完成字符串拷贝
stop
        MOV     R0,     #0x18	         ; 程序结束返回编译器调试环境
        LDR      R1,     =0x20026
        SWI        0x123456
strcopy 
        LDRB     R2,     [R1],    #1    ; 将R1指向的单元内容加载到R2中
        STRB      R2,     [R0],    #1    ; 将R2中的数存储到R0指向的单元中
        CMP       R2,    #0                 ; 检查R0的值是否等于0
        BNE        strcopy                  ; 如果不等于0,那么转到strcopy处执行 
        MOV       PC,    LR               ; 子程序返回 
        
        AREA    Strings, DATA, READWRITE
srcstr  DCB "First string - source",0		; 源字符串
dststr  DCB "Second string - destination",0	; 目的字符串
        END 

结果如下

R0=&dststr=0x40000000
R1=&srcstr=0x00000038

在这里插入图片描述

②存储区域传递参数方式

Jump.s

       AREA    Jump, CODE, READONLY
num EQU 4			; 函数地址表内容的个数
       ENTRY
       CODE32
start
     LDR   R0,   =choice		; R0指向存储区的choice单元
       LDR   R0,   [R0]		; 设置第一个参数:选择执行哪一个函数
       MOV  R1,   #16		; 设置第1个操作数
       MOV  R2,   #2		; 设置第2个操作数
       BL       arithfunc		; 调用子程序arithfunc
stop
       MOV   R0,   #0x18		; 程序结束返回编译器调试环境
       LDR    R1,   =0x20026
       SWI	     0x123456
arithfunc
       CMP   R0,    #num                     ; 比较R0的值是否超过函数地址表的个数
       MOVHS   PC, LR  		; 如果大于,那么就返回到标号stop处
       ADR   R3,    JumpTable	; 将函数地址表的地址作为基地址
       LDR    PC,   [R3, R0, LSL #2]	; 根据R0参数进入对应的子程序
       
JumpTable	; 函数地址表的入口基地址
        DCD     	DoAdd		; 加法子程序
        DCD	DoSub		; 减法子程序
        DCD	DoMul		; 乘法子程序
        DCD	DoDiv		; 除法子程序
DoAdd
        ADD   R0,   R1,    R2               ; R0 = R1 + R2
        MOV   PC,   LR		; 返回
DoSub
        SUB    R0,	R1,    R2      	; R0 = R1 - R2
        MOV   PC,	LR		; 返回
DoMul	
        MOV   R0,   R1,  LSL R2 	; R0 = R1 << R2
        MOV   PC,   LR 		; 返回
DoDiv	
        MOV   R0,   R1,  LSR R2      	; R0 = R1 >> R2
        MOV   PC,   LR	 	; 返回		
	  AREA  NUM, DATA, READWRITE
choice	DCD	3           ; 0:表示选择加法子程序   1:表示选择减法子程序
		             ; 2:表示选择乘法子程序   3:表示选择除法子程序
        END

说明
类似:函数指针的用法

       ADR   R3,    JumpTable			; 将函数地址表的地址作为基地址
       LDR    PC,   [R3, R0, LSL #2]	; 根据R0参数进入对应的子程序

结果如下

R0=16/1<<2=4
在这里插入图片描述

③ 堆栈传递参数方式

最后

2023-4-6 22:29:06
2023-4-11 19:17:12

祝大家逢考必过
点赞收藏关注哦

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

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

相关文章

一文看懂多模态大型语言模型GPT-4

文章目录前言什么是GPT-4GPT-4 VS GPT-3.5GPT-4与其他模型对比GPT-4视觉输入GPT-4局限性写在最后前言 近日&#xff0c;OpenAI发布了最新版的生成预训练模型GPT-4。据官方介绍&#xff0c;最新一代的模型是一个大模型&#xff0c;性能比CPT-3.5强悍很多&#xff0c;不仅仅是接…

泛微数字化安全管理,实现标准化、智能化管理,数据可视化分析

企业安全管理需求提升&#xff1a; 随着国家政策与技术的双重驱动&#xff0c;企业当前的安全管理需求&#xff0c;从标准化管理&#xff0c;逐步发展到智能、可视、可分析的全程数字化安全管理&#xff0c;落地风险分级管控、隐患排查治理的双重预防机制。 国家发布的《企业…

腾讯云轻量级云服务器Centos7防火墙开放8080端口

腾讯云轻量级云服务器Centos7防火墙开放8080端口 一、centos7防火墙打开端口 因为Centos7以上用firewalld代替了iptables,也就是说firewalld开通了8080端口应该就行了 1.查看8080是否已经放开 sudo firewall-cmd --permanent --zonepublic --list-ports2.查看防火墙状态 s…

电子标准院、中信银行、优云牵头!《数据中心服务能力成熟度模型》国标修订研讨会成功举办

4月11日&#xff0c;GB/T 33136 -2016《数据中心服务能力成熟度模型》国标修订第五次研讨会议在广州顺利召开。本次会议由中国电子技术标准化研究院、中信银行、广通优云牵头发起&#xff0c;广州赛宝认证中心承办&#xff0c;云下科技协办。 来自政府、金融、电信、能源、交通…

SQL Server 连接查询和子查询

提示&#xff1a; 利用单表简单查询和多表高级查询技能&#xff0c;并且根据查询要求灵活使用内连接查询、外连接查询或子查询等。同时还利用内连接查询的两种格式、三种外连接查询语法格式和子查询的语法格式。 文章目录前言1.查询所有学生的学号、姓名、选修课程号和成绩方法…

Python零基础自学

很多零基础想做程序员的同学&#xff0c;最开始接触的基本上都是 Python 作为常年霸榜的 “最好上手的编程语言” ——Python&#xff0c;深受互联网大厂的喜爱。 而很多小伙伴反应&#xff0c;在刚开始学Python时遇到不少问题&#xff1a; 比如找不到学习资源&#xff0c;不…

多态--遗失的子类析构函数(重要)

通过阅读下面的代码以及将其置于编译器上编译运行: #include<iostream> using namespace std;class Father { public:Father(const char* addr"中国") {cout << "执行Father类构造函数" << endl;int len strlen(addr) 1;this->add…

.Net Forms Resize V12.0 Crack

.Net Forms Resize V12.0 添加对 .NET 7 的支持并改进调整大小引擎。2023 年 4 月 14 日 - 10:27新版本特征 添加了对 Microsoft Visual Studio 2022 (v17.5.3) 及更高版本的支持。添加了对 Microsoft Windows Server 2019 和 2022 的支持。改进和调整引擎大小&#xff08;快约…

认识JVM

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录JVM 内存区域划分栈程序计数器堆元数据区JVM 类加载机制加载验证准备解析初始化双亲委派模型JVM 垃圾回收机制GC 实际工作过程…

Java基础之哈希表与红黑树

文章目录一、哈希表1.1 JDK1.7版本之前哈希表&#xff08;数组链表&#xff0c;头插法&#xff09;1.2 JDK1.8版本之后哈希表&#xff08;数组链表红黑树&#xff0c;尾插法&#xff09;二、红黑树2.1 使红黑树再次满足红黑规则2.1.1 使红黑树满足红黑规则方法一2.1.2 使红黑树…

JavaSE学习进阶day03_01 多态

第一章 多态 1.1 多态的形式 直接说什么是多态性太抽象了&#xff0c;我们先引入一个例子&#xff1a; 现在我定义了一个feed方法&#xff0c;在不同的类的对象调用这个方法时&#xff0c;都要改变形参&#xff0c;即每当我的对象不同时&#xff0c;都要重载该方法&#xff0…

【Java基础】day13

day13 一、Spring Bean 生命周期是怎样的&#xff1f; 详细过程分为以下几个步骤&#xff1a; ① 初始化 Bean 容器通过获取 BeanDefinition 中的信息进行实例化&#xff0c;这一步仅仅是简单的实例化&#xff0c;并没有进行依赖注入。 实例化的对象被包装在 BeanWrapper 对…

Qt音视频开发38-ffmpeg视频暂停录制的设计

一、前言 基本上各种播放器提供的录制视频接口&#xff0c;都是只有开始录制和结束录制两个&#xff0c;当然一般用的最多的也是这两个接口&#xff0c;但是实际使用过程中&#xff0c;还有一种可能需要中途暂停录制&#xff0c;暂停以后再次继续录制&#xff0c;将中间部分视…

RabbitMq架构设计原理

文章目录1、消息中间件1.1、什么是消息中间件1.2、传统的HTTP请求有什么缺点1.3、MQ的应用场景2、同步、多线程、以及MQ处理业务逻辑的区别2.1、同步发送Http 请求2.2、多线程处理业务逻辑2.3、MQ实现业务逻辑Mq和多线程之间的区别3、Mq消息中间件名词4、简单实现Mq的思路4.1、…

MySQL索引15连问,你能坚持到第几问?

目录 1.索引是什么? 2.MySQL索引有哪些类型 3.索引什么时候会失效? 4.哪些场景不适合建立索引? 5.为什么要用 B树&#xff0c;为什么不用二叉树? 6.一次B树索引树查找过程 7.什么是回表? 如何减少回表? 8.什么是覆盖索引? 9.聊聊索引的最左前缀原则 10.索引下…

Phind——一款面向开发人员的AI搜索引擎

目录前言一、Phind优点二、使用方法总结前言 Phind是一款面向开发人员的AI搜索引擎&#xff0c;它由大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;驱动 。相比于传统的搜索引擎&#xff0c;Phind有以下优势&#xff1a;自然语言搜索、面向开发者、AI…

【数据结构】期中考试一把梭(通宵版上)

前言 红中(Hong_zhong) CSDN内容合伙人、2023年新星计划web安全方向导师、 吉林师范大学网安大一的一名普通学生、摸鱼拿过大挑校二、 华为MindSpore截至目前最年轻的优秀开发者、IK&N战队队长、 阿里云专家博主、华为网络安全云享专家、腾讯云自媒体分享计划博主、 划了…

URL 和 HandlerMapping建立映射(11)

上一篇https://blog.csdn.net/chen_yao_kerr/article/details/130194864 我们已经分析了Spring MVC的配置&#xff0c;并且说明了如何通过注解的方式去替换各种各样的xml配置文件。本篇将更深入分析&#xff1a; 取代 springmvc.xml 配置 之前我们说过&#xff0c;定义一个类…

简述API(电商数据API)网关的概念和功能

API 网关 ( API gateway ) 前言 在 IOT &#xff08; 物联网 &#xff09;中&#xff0c;当我们的一些设备。例如&#xff08; 监控、传感器等 &#xff09;需要将收集到的数据和信息进行汇总时&#xff0c;我们就需要一个 API。&#xff08;如果你需要Taobao/JD/pinduoduo平台…

OpenAI-ChatGPT最新官方接口《语音智能转文本》全网最详细中英文实用指南和教程,助你零基础快速轻松掌握全新技术(六)(附源码)

Speech to text 语音智能转文本Introduction 导言Quickstart 快速开始Transcriptions 转录python代码cURL代码Translations 翻译python代码cURL代码Supported languages 支持的语言Longer inputs 长文件输入Prompting 提示其它资料下载Speech to text 语音转文本 Learn how to …