## ARM基础编程实验

在这里插入图片描述

ARM基础编程实验

作者: Saint
掘金:https://juejin.im/user/5aa1f89b6fb9a028bb18966a
微博:https://weibo.com/5458277467/profile?topnav=1&wvr=6&is_all=1
GitHub:github.com/saint-000
CSDN: https://me.csdn.net/qq_40531974

一、实验目的
1.熟悉并掌握常用ARM汇编指令
2.熟悉并掌握“C+汇编”混合编程技术
3.熟练使用ARM软件开发调试工具Keil

二、实验内容
1.学习使用Keil开发工具。
2.使用ARM汇编语言,编程实现1+2+……+N累加运算功能。
3.使用C调用汇编函数,实现字符串拷贝功能。
4.使用汇编调用C函数,实现求和运算功能。
5.使用ARM汇编语言,实现冒泡排序算法。

三、实验步骤
实验1.1:运行Keil,建立工程文件,单步运行调试演示示例程序,深刻理解每一条指令,观察寄存器,内存空间的变化。ARM数据处理指令寻址方式实验和ARM内存访问指令寻址方式实验,ARM堆栈指针寄存器实验、ARM程序计数器实验、ARM程序状态寄存器实验、ARM工作模式切换实验。

实验1.2:用ARM汇编实现1+2+…+N的累加运算
1.将实验1.2文件夹中的sum.s文件添加至工程中。
2.在文件中,用汇编实现算法核心部分,需添加的代码参考流程图如下:
在这里插入图片描述
3. 运行Debug进行调试。

实验1.3:理解C和汇编,并用汇编程序实现字符串拷贝,并在C程序中调用该汇编程序。
1.将实验1.3文件夹中的testfile.s和main.c文件添加至工程中。
2.在汇编文件testfile.s中添加两行汇编代码,分别实现:
(1) 拷贝源字符串的一个字节到R2中;
(2) 将拷贝的字节复制到目标空间。
(3)运行Debug进行调试。

实验1.4:在汇编中调用C函数。
1.将实验1.4文件夹中的sum.c和testfile.s文件添加至工程中。
2.在汇编文件testfile.s中相应位置添加汇编代码,通过调用c函数g()实现1+2+3+glovb1,结果存在R8中。
3.运行Debug进行调试,观察实验现象。

实验1.5:用ARM汇编实现冒泡算法。
1.将实验1.5文件夹中的maopao.s文件添加至工程中。
2.在汇编文件maopao.s中相应位置添加汇编代码,实现冒泡排序。
3.运行Debug进行调试。
4.在debug界面,点击Debug →Memory Map,修改地址分段属性。
5.观察实验现象

四、实验结果
实验1.1ARM数据处理指令寻址方式实验和ARM内存访问指令寻址方式实验中代码如下:
在这里插入图片描述

在这里插入图片描述
通过调试可以发现知道代码中的数据传送指令MOV;算术运算指令-加法指令ADD和减法指令SUB;以及比较指令CMP等数据处理指令在寄存器的数值和地址的变化,初步了解ARM的寻址方式以及数据传送方式。

实验1.2编程实现1+2+…+N 代码书写:

 ;功能:计算1+2+3+4+...+N
    ;说明;N>=0,当N=0时结果为0,当N=1时结果为1
    N EQU 100   ;定义N的值100
    	AREA Examples,CODE,READONLY   ;声明代码断Examples3
    	ENTRY   ;标识程序入口 
    	
	CODE32
ARM_CODE
LDR SP,=0X30003F00    ;设置堆栈指针
	ADR R0,THUMB_CODE+1    
	BX R0        ;跳转并切换处理器状态
	LTORG        ;声明文字池	
CODE16
THUMB_CODE
LDR R0,=N    ;设置子程序SUM_N的入口参数 
	BL SUM_N     ;调用子程序SUM_N
	B THUMB_CODE 
	
;SUM_N
;功能:计算1+2+3+......+N
;入口参数:R0 N的值
;出口参数:R0 运行结果 
;占用资源:R0
;说明:当N=0时结果为0,当N=1时结果为1
;若运算溢出,结果为0
SUM_N
	PUSH {R1-R7,LR}  ;寄存器入栈保护
	MOVS R2,R0       ;将n的值复制到R2,并影响相应条件标志
	BEQ SUM_END      ;若N=0,则返回,成立即返回
	CMP R2,#1		 ;比较R2是否为1
	BEQ SUM_END      ;若N=1,则返回,成立即返回
	MOV R1,#1        ;初始化计数器R1=1									MOV R0,#0        ;初始化计数器R0=0 
SUN_L1
	ADD R0,R1		 ;R0=R1+R0
	BVS SUM_END		 ;溢出	
	CMP R1,R2		 ;比较R1和n是否相等
	BVS SUM_END		 ;相等,跳出循环,即加到n结束
	ADD R1,#1		 ;R1=R1+1;
	B SUN_L1		 ;跳转循环
SUM_ERR
	MOV R0,#0		;R0=0
SUM_END 
	MOV R8,R0		 ;将结果保存在R8中
	POP {R1-R7,PC}   ;寄存器出栈,返回
        
	END

实验结果:
最终寄存器R8的读数为为0X000013BA,数值为十进制的5050,正好是从1加至100之和,所以成功实现该功能。

实验1.3理解C和汇编,并用汇编程序实现字符串拷贝,并在C程序中调用该汇编程序。
在C程序中调用该汇编程序

;文件名:main.c
;功能:完成字符串的拷贝
#include <stdio.h>
extern void strcopy(char *d ,char *s);
int main(void)
{
	char *srcstr = "aaaa";
	char dststr[] = "bbbb";
	//printf("Before copying:\n");				//仿真调试时禁用printf语句
	//printf(" %s %s\n",srcstr,dststr);
	strcopy(dststr,srcstr);
	//printf("After copying: \n");
	//printf(" %s\n  %s\n",srcstr,dststr);
	return (0);

}

;文件名:TEST.S 
;功能:从C语言中调用汇编语言
AREA	Example1,CODE,READONLY	;声明代码段Example1 
CODE32				   ;声明32位ARM指令
IMPORT __main
EXPORT strcopy
strcopy	
	LDRB  R2,[R1],#1	;拷贝源字符串的一个字节
	STRB  R2,[R0],#1	;将拷贝的字节复制到目标空间,
	CMP   R2,#0		;比较R2=0
	BNE   strcopy	
	MOV   PC,LR
	END			     	  

实验结果:
将原来的aaaa bbbb的值变成了aaaa aaaa,所以成功实现字符串复制。
在这里插入图片描述在这里插入图片描述

实验1.4在汇编中调用C函数

;文件名:main.c
;功能:完成求和
int g(int a, int b ,int c,int d)
{
	return a+b+c+d;
}

;文件名:TESTFILE.S 
;功能:从汇编语言中调用C语言
		IMPORT g
AREA	Example1,CODE,READONLY	  	
		CODE32				  	
		ENTRY
START	
		MOV		R0,#1	
		MOV		R1,#2
		MOV		R2,#3
		MOV		R3,#10
		BL		g
		MOV		R8,R0	
		B		START

		END

实验结果:
最终寄存器R8读数为0X000010,正好为1+2+3+10=16,所以正确实现该功能。

实验1.5用ARM汇编实现冒泡算法。

 AREA Sort,CODE,READONLY
	ENTRY
start
	MOV r4,#0
	LDR r6,=src
	ADD r6,r6,#len
outer
	LDR r1,=src
inner
  LDR r2,[r1]
  LDR r3,[r1,#4]
  CMP r2,r3
  STRGT r3,[r1]
  STRGT r2,[r1,#4]
  ADD r1,r1,#4
  CMP r1,r6
  BLT inner
  
  ADD r4,r4,#4
  CMP r4,#len
  SUBLE r6,r6,#2
  BLE outer
src DCD 2,4,10,8,14,1,20
    AREA Array,DATA,READWRITE
len EQU 7*4
END

实验结果:
从起始寄存器位置开始,每个四个输出一个数据,数据依次为1,2,4,8,10,14,20,由此完成了冒泡排序法。
在这里插入图片描述
五、实验总结
1、学习使用Keil开发工具。
2、完成了1+2+…+N求和,N=100时答案为5050。
3、C语言中调用了汇编语言,实现字符串复制。
4、汇编中调用了C语言函数,实现了实现求和运算功能。
5、用汇编语言实现了冒泡排序法,结果为1,2,4,8,10,14,20。

实验心得:
(1)在写冒泡排序过程中发现,如果使用杂项伪命令AREA定义数据段时, AREA Sort,CODE,READONLY这段代码要缩进,以及跟下面结束时的相同代码对齐,否则会出现编译错误。
在这里插入图片描述

(2)我们在使用memory map的时候,需要查看同一个寄存器的首地址和尾地址的数据变化,我们需要将程序刚开始的寄存器首地址和结束时的尾地址填入memory map中,注意格式如下:
在这里插入图片描述
在这里插入图片描述

六、实验思考题
1.ADD替换成ADDS,SUB替换成SUBS有什么影响?
运算结果不影响CPSR中相应标志位的值,跳转指令因为上一步的CPSR的值没有改变而无法正确执行。S用于决定指令的操作是否影响CPSR中的条件标志位。

2.MOV替换成MOVNE有什么影响?
只有在上一步计算结果为不相等时才执行。MOVNE先判断条件NE (不相等)则转移,可以看作是两条指令NE=NOT EQUAL不相等。

3.STMIA换成STMIB,STMIA换成STMDA有什么区别?
STMIA换成STMIB是将每次写入前地址+4改为地址-4,STMIA换成STMDA是将每次写入前地址+4改为+1 ,其中STMIB(地址先增而后完成操作)、STMFA(满递增堆栈);

STMIA(完成操作而后地址递增)、STMEA(空递增堆栈);STMDB(地址先减而后完成操作)、STMFD(满递减堆栈);STMDA(完成操作而后地址递减)、STMED(空递减堆栈)。

4.思考用ARM汇编实现1+3+5+…+(2n+1)或者2+4+6+…+2n。
实现1+3+5+„.+(2n+1):

将 add r1,r1,#1 改为 add r1,r1,lsl  #1       sub r1,r1,#1   
实现2+4+6+…..+2n:   
将 add r1,r1,#1 改为 add r1,r1,lsl  #1  

5.实验3中如果去除汇编代码中的“EXPORT strcopy”会有什么现象,为什么?
C语言无法调用用strcopy函数。因为EXPORT伪指令用于在程序中声明一个全局的标号,该标号可在其他的文件中引用。

6.实验4中如果去除汇编代码中的“IMPORT ……”会有什么现象,为什么?
在这里插入图片描述
把“IMPORT ….注释后发现,编译调试时程序单步运行直接从汇编程序开始,说明无法调用C语言的main函数。IMPORT伪操作告诉编译器当前的符号不是在本源文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号,而且不论本源文件是否实际引用该符号,该符号都将被加入到本源文件的符号表中。

  • 21
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值