汇编第二次上机实验(续第一次,字符串比较及双重循环)【嵌入式系统】
- 前言
- 推荐
- 说明
- 汇编第二次上机实验(续第一次,字符串比较及双重循环)
- 内容
- 1 sort
- 说明
- 流程图
- 代码编写
- 结果分析
- 2 string
- 流程图
- 代码编写
- 结果分析
- 3 Bibble
- 流程图
- 代码编写
- 结果分析
- 4 factorial
- 流程图
- 代码编写
- 结果分析
- 5 略
- 最后
前言
2023-4-14 21:29:03
以下内容源自《创作模板三》
仅供学习交流使用
推荐
ARM汇编第一次上机(顺序、分支、单重循环)【嵌入式系统】
说明
请见ARM汇编第一次上机(顺序、分支、单重循环)【嵌入式系统】说明
汇编第二次上机实验(续第一次,字符串比较及双重循环)
内容
按照要求编程实现以下功能,简要写出设计思路,画出程序流程图,并把调试结果截图附录,提交实验报告。
录制上传视频,演示实验并讲述主要过程。(10分钟左右视频)
1、修改排序程序,按照字节方式排序,画出编程思路及程序流程。(5分)
2、编程实现统计任意两个字符串各自包含的字符个数的功能,约定字符串以0为结束标志,然后对这两个字符串判断是否匹配(是否一致)?灵活一点可以给定3个字符串,然后进行比较。(基本功能8分,字符统计4分,字符串比较4分)
3、课本第11题,参考冒泡排序程序完成编程与调试(7分)
4、编写一个求阶乘 N!的 ARM 汇编程序,给定N 值(10~20中间取值),然后完成求和运算:SUM=1!+2!+…+N!。(5分)
5、附加功能,结合C语言,在第4题基础上增加输入、输出人机交互功能,根据输入字符统计字符个数并比较输入的字符串是否匹配,打印显示结果。(10分)
1 sort
说明
第一点 为什么拷贝数组
首先,Keil4会把READWITER区初始化为0
其次,原始数据放到READONLY区,将不能改变
所以,要把原数数据(READONLY)拷贝到拷贝数组(READWITER)中,进行排序
第二点 右指针的计算
LDR R1,=nums ; (右指针)R1起初指向src第一个单元
LDRB R4, count ; R4中是数据区中待排序数据个数
SUB R4, R4, #1 ; R4--
ADD R1,R1,R4 ;(右指针)R1指向src最后一个单元 R1=R1+R4*1,
参见如下C语言
此处,不做过得解释
#include<stdio.h>
int main(){
int nums[10]={0,1,2,3,4,5,6,7,8,9};
int *p=nums;//nums[0]的地址
printf("%x\n",p);//62fdf0
p=p+9;//nums[9]的地址
printf("%x\n",p);//62fe14
printf("%d\n",*p);//9
}
//地址计算
//0x62fdf0+36=0x62fe14
//address9=address0+9*sizeof(int)
//sizeof(int) =4
流程图
此处简画流程图
知道冒泡排序的思想即可
具体实现
可以结合注释
查看代码即可
代码编写
AREA sort, CODE, READONLY
ENTRY
start
;实现数组拷贝 需要输入原数组 数组长度 输出目的数组 即可
LDR R1,=nums0 ; R1指向数据区的源字符串
LDR R0,=nums ; R0指向数据区的目的字符串
LDRB R3,count ;数组个数
BL numscopy ; 调用子程序numscopy,完成数组拷贝
LDR R1,=nums ; (右指针)R1起初指向src第一个单元
MOV R2, #0 ; 用于外层循环控制计数器,并初始化为0
LDRB R4, count ; R4中是数据区中待排序数据个数
SUB R4, R4, #1 ; R4--
ADD R1,R1,R4 ;(右指针)R1指向src最后一个单元 R1=R1+R4*1,
outer ; 外层循环
LDR R0, =nums ;(左指针)R0指向数据区src单元
inner ; 内层循环
LDRB R5, [R0] ; 将R0所指向单元的数加载到R5中
LDRB R6,[R0, #1] ; 将相邻单元的数加载到R6中
CMP R5, R6 ; 比较相邻两单元中的数
STRBGT R6, [R0] ;如果前者大于后者,那么两个数交换
STRBGT R5, [R0, #1] ; 内层循环修改、控制部分
ADD R0, R0, #1 ; 地址指针向下拨移1个字节
CMP R0, R1 ; 是否扫描了一遍
BNE inner ; 没有完成一遍,继续内循环
; 外层循环修改、控制部分,表示已经完成了一遍,
ADD R2, R2, #1 ; 外层循环控制计数器加1
SUB R1, R1, #1 ; 右指针R1向左指针方向移动1字节
CMP R2, R4 ; 是否全部扫描
BNE outer ; 没有完成全部扫描,继续外循环
stop
MOV R0, #0x18 ; 程序结束返回编译器调试环境
LDR R1, =0x20026
SWI 0x123456
numscopy
LDRB R2, [R1], #1 ; 将R1指向的单元内容加载到R2中
STRB R2, [R0], #1 ; 将R2中的数存储到R0指向的单元中
SUBS R3,R3,#1 ;R3--
CMP R3, #0 ; 检查R0的值是否等于0
BNE numscopy ; 如果不等于0,那么转到strcopy处执行
MOV PC, LR ; 子程序返回
AREA BlockData0, DATA, READONLY
nums0 DCB 1,2,3,4,5,9,8,7,6,0
count DCB 10
AREA BlockData, DATA, READWRITE
nums DCB 1,2,3,4,5,9,8,7,6,0 ;Keil会把此数组初始化为0
END
结果分析
数组拷贝
初始化右指针
R1=0x40000009 //右指针指向数组的最右端
R2=0 //计算器
R4=9 //外循环次数
第一遍排序
R1=0x40000008 //右指针左移
R2=1 //计算器+1
R5,R6用于交换相邻数组元素
排序完成
R2=R4=9
2 string
流程图
代码编写
AREA string ,CODE, READONLY
ENTRY
CODE32
start
LDR R1,=str1 ; R1指向数据区的源字符串1
LDR R3,=0 ;暂存长度
BL length ; 调用子程序length,完成求长度
MOV R4,R3 ;R4存str1的长度
LDR R3,=0 ;暂存长度
LDR R1,=str2 ; R1指向数据区的目的字符串2
BL length ; 调用子程序length,完成求长度
MOV R5,R3 ;R5存str2的长度
LDR R1,=str1
LDR R2,=str2
BL compare
LDR R9,=eqstate
STRB R8,[R9]
stop
MOV R0, #0x18 ; 程序结束返回编译器调试环境
LDR R1, =0x20026
SWI 0x123456
;求字符串长度 输入R1 字符串起始地址 返回R3长度
length
ADD R3,R3,#1 ;R3++
LDRB R2, [R1,#1]! ; 将R1+1指向的单元内容加载到R2中 先前1位搜索
CMP R2, #0 ; 检查R2的值是否等于0
BNE length ; 如果不等于0,那么转到length处执行
MOV PC, LR ; 子程序返回
;比较字符串是否相等
;输入R1 str1的地址 R4 str1的长度 R2 str2的地址 R5 str2的长度
;输出 R8 比较结果 ;0表示不一样 1表示一样
compare
;比较长度是否相等
CMP R4,R5
MOVNE R8,#0
MOVNE PC, LR ; 子程序返回
MOV R4,#0 ;作为计数
loop
LDRB R6,[R1],#1 ;R6遍历str1
LDRB R7,[R2],#1 ;R7遍历str2
CMP R6,R7 ;字符不相等
MOVNE R8,#0 ;即字符串不相等
MOVNE PC,LR ; 子程序返回
ADD R4,R4,#1 ;计数器
CMP R4,R5 ;控制循环次数
BNE loop
MOV R8,#1 ;遍历完 即为相等
MOV PC,LR ; 子程序返回
AREA Strings0, DATA, READONLY
str1 DCB "12345",0 ; 源字符串1
str2 DCB "12345",0 ; 源字符串2
AREA Strings, DATA, READWRITE
eqstate DCB 0 ;0表示不一样 1表示一样
END
结果分析
求长度
R4=5
R5=5
比较结果
R8=1
[0x40000000]=0x01
3 Bibble
流程图
与1相同
代码编写
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 ;R4--
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
结果分析
分析过了:略
4 factorial
流程图
代码编写
AREA factorial, CODE, READONLY
ENTRY
start
;迭代算法思想 把每个阶乘放到数组中 接着求和 避免阶乘的重复计算
;1!=1
;n!=n*(n-1)!
LDR R0,n ; R0是n
LDR R1,=1 ; R1是计数器 1->n
LDR R2,=nums ; R2指向nums
STR R1,[R2] ;放入1!
ADD R1,R1,#1 ;从2开始
loop
LDR R3,[R2] ;R3=(n-1)!
MUL R4,R1,R3 ;R4=n*(n-1)!
STR R4,[R2,#4]!; ;存入
ADD R1,R1,#1 ;R1++
CMP R1,R0
BLS loop
LDR R0,n ; R0是n
LDR R1,=1 ; R1是计数器 1->n
LDR R2,=nums ; R2指向nums
LDR R5,=sum ; R5指向sum
LDR R6,=0 ; R6存入sum
sumloop
LDR R3,[R2],#4 ;R3取出遍历数组的值 ;R3=[R2++]
ADD R6,R6,R3 ;R6+=R3
ADD R1,R1,#1 ;R1++
CMP R1,R0
BLS sumloop
STR R6,[R5] ;存入
stop
MOV R0, #0x18 ; 程序结束返回编译器调试环境
LDR R1, =0x20026
SWI 0x123456
AREA BlockData0, DATA, READONLY
n DCD 4
AREA BlockData, DATA, READWRITE
nums DCD 1,2,3,4,5,9,8,7,6,0 ;Keil会把此数组初始化为0
sum DCD 0
END
结果分析
当n=4时
求阶乘
01 02 06 18
阶乘求和
01+02+06+18=21
当n=10时
0x003D9D19=4037913
5 略
最后
2023-4-14 23:40:30
你对我百般注视,并不能构成万分之一的我,却是一览无余的你。
祝大家逢考必过
点赞收藏关注哦