ARM基础编程实验
目录
一、实验目的
1.熟悉并掌握常用ARM汇编指令2.熟悉并掌握“C+汇编”混合编程技术3.熟练使用ARM软件开发调试工具Keil
二、实验内容
1.学习使用Keil开发工具2.实现累加运算功能
3.实现字符串拷贝功能4.实现求和运算功能
5.实现冒泡排序算法
三、实验步骤
实验1.1:运行Keil,建立工程文件,单步运行调试演示示例程序,深刻理解每一条指令,观察寄存器,内存空间的变化。
此处提供六个示例实验:
其中ARM数据处理指令寻址方式实验和ARM内存访问指令寻址方式实验为必做实验。
ARM堆栈指针寄存器实验、ARM程序计数器实验、ARM程序状态寄存器实验、ARM工作模式切换实验为选做部分,鼓励大家利用课上剩余时间或课后完成此部分内容。
Keil的具体使用步骤如下:
1.点击“Keil uVision5”打开软件主窗口。
2.点击Project->New uVision Project建立新工程。
3.为新工程命名。
4.为工程选择目标器件:三星S3C2440A。
5.选择是否添加S3C2440.s启动文件:C源程序工程选“是”,汇编源程序工程选“否”。
6.在工程Source Group上点右键选择添加新工程文件。
7.选择源文件类型。
8.录入源代码并保存。
9.对工程进行build或rebuild。
10.点击debug按钮进入/退出调试,忽略代码大小限制。使用单步调试,仔细观察过程中关键寄存器值的变化。
实验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.1实验一 |
ARM数据处理指令寻址方式 ARM内存访问指令寻址方式实验 ARM堆栈指针寄存器实验 ARM程序计数器实验 ARM程序状态寄存器实验 ARM工作模式切换实验 |
1.2实验部分关键代码: |
ADD R0,R1 BVS SUM_END CMP R1,R2 BHS SUM_END ADD R1,#1 B SUN_L1 |
1.2实验结果: |
可以看到,R0和R8中的值为13BA,符合1+2+…+100的实验结果 |
1.3实验部分关键代码: |
LDRB R2,[R1],#1 ;拷贝源字符串的一个字节 STRB R2,[R0],#1 ;将拷贝的字节复制到目标空间 CMP R2,#0 BNE strcopy MOV PC,LR ;------------------------------------------ END ;文件结束 |
1.3实验结果: |
字符串变量由’bbbb’拷贝为’aaaa’ |
1.4实验部分关键代码: |
MOV R0,#1; MOV R1,#2; MOV R2,#3; MOV R3,#10; BL g MOV R8,R0; |
1.4实验结果: |
可以看到R0中的值再相加之后变为了0x10,结果为16,符合实验的预期。 |
1.5冒泡排序实验部分关键代码: |
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,#4 BLE outer |
1.5实验结果: |
五、实验总结
1.此次实验用汇编和C语言实现了1~N的累加、字符串的拷贝、数字求和以及冒泡法排序这几项功能,了解了汇编语言的基础指令及其意义,同时初步入门了Keil编译器的使用与程序编写调试。
2.知道了C程序与汇编语言相互调用的规则:
a)寄存器的使用规则:“子程序间”通过寄存器R0~R3来传递参数。在“子程序中”,使用寄存器R4~R11来保存局部变量。
b)寄存器R12用于子程序间scratch寄存器(用于保存SP,在函数返回时使用该寄存器出桟),记作IP。
c)寄存器R13用于数据栈指针,记作SP。寄存器SP在进入子程序时的值和退出子程序时的值必须相等。
d)寄存器R14称为链接寄存器,记作LR。它用于保存子程序的返回地址。
e)寄存器R15是程序计数器,记作PC。
六、实验思考题
1、ADD替换成ADDS ,SUB替换成SUBS有什么影响?替换后,运算结果会影响标志寄存器。因为ADD、SUB不带进位与借位,ADDS、SUBS带有进位与借位,运算完成要置符号位。
2、MOV替换成MOVNE有什么影响?替换后只有在上一步计较结果为不相等的时候才会执行该指令。
3、STMIA换成STMIB ,STMIA换成STMDA有什么区别?换成STMIB是将每次传送后的地址+4变成每次传送前地址+4,换成STMDA是将每次传送后的地址+4变成每次传送后地址-4。
4、思考用ARM汇编实现1+3+5+….+(2n+1)或者2+4+6+…..+2n。实现前者,将ADD R1,#1改为ADD R1,#2,并设置R1初始值为1。
实现后者,将ADD R1,#1改为ADD R2,#2,设置R1初始值为2。
5、实验3中如果去除汇编代码中的“EXPORT strcopy”会有什么现象,为什么?若去除汇编代码中的‘EXPORT strcopy’,则在C语言里面无法调用该函数,因为EXPORT用于声明strcopy为全局标号。
6、实验4中如果去除汇编代码中的“IMPORT …..” 会有什么现象,为什么?
会无法调用C语言的main函数,因为该伪指令用于通知编译器要使用的标号或者变量在其他的源文件定义。