汇编第二次上机实验(续第一次,字符串比较及双重循环)【嵌入式系统】
汇编第二次上机实验(续第一次,字符串比较及双重循环)【嵌入式系统】
- 前言
- 推荐
- 说明
- 汇编第二次上机实验(续第一次,字符串比较及双重循环)
-
- 内容
- 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);//62fdf0p=p+9;//nums[9]的地址 printf("%x\\n",p);//62fe14printf("%d\\n",*p);//9
} //地址计算 //0x62fdf0+36=0x62fe14//address9=address0+9*sizeof(int) //sizeof(int) =4
流程图
此处简画流程图
知道冒泡排序的思想即可
具体实现
可以结合注释
查看代码即可
代码编写
AREA sort, CODE, READONLYENTRY
start;实现数组拷贝 需要输入原数组 数组长度 输出目的数组 即可LDR R1,=nums0 ; R1指向数据区的源字符串LDR R0,=nums ; R0指向数据区的目的字符串LDRB R3,count ;数组个数BL numscopy ; 调用子程序numscopy,完成数组拷贝LDR R1,=nums ; (右指针)R1起初指向src第一个单元 MOV R2, #0 ; 用于外层循环控制计数器,并初始化为0LDRB 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 ; 外层循环控制计数器加1SUB R1, R1, #1 ; 右指针R1向左指针方向移动1字节CMP R2, R4 ; 是否全部扫描 BNE outer ; 没有完成全部扫描,继续外循环
stopMOV R0, #0x18 ; 程序结束返回编译器调试环境LDR R1, =0x20026SWI 0x123456numscopy LDRB R2, [R1], #1 ; 将R1指向的单元内容加载到R2中STRB R2, [R0], #1 ; 将R2中的数存储到R0指向的单元中SUBS R3,R3,#1 ;R3--CMP R3, #0 ; 检查R0的值是否等于0BNE numscopy ; 如果不等于0,那么转到strcopy处执行 MOV PC, LR ; 子程序返回 AREA BlockData0, DATA, READONLY
nums0 DCB 1,2,3,4,5,9,8,7,6,0
count DCB 10AREA BlockData, DATA, READWRITE
nums DCB 1,2,3,4,5,9,8,7,6,0 ;Keil会把此数组初始化为0END
结果分析
数组拷贝
初始化右指针
R1=0x40000009 //右指针指向数组的最右端
R2=0 //计算器
R4=9 //外循环次数
第一遍排序
R1=0x40000008 //右指针左移
R2=1 //计算器+1
R5,R6用于交换相邻数组元素
排序完成
R2=R4=9
2 string
流程图
代码编写
AREA string ,CODE, READONLYENTRYCODE32
startLDR R1,=str1 ; R1指向数据区的源字符串1LDR R3,=0 ;暂存长度BL length ; 调用子程序length,完成求长度MOV R4,R3 ;R4存str1的长度LDR R3,=0 ;暂存长度LDR R1,=str2 ; R1指向数据区的目的字符串2BL length ; 调用子程序length,完成求长度MOV R5,R3 ;R5存str2的长度LDR R1,=str1LDR R2,=str2 BL compareLDR R9,=eqstateSTRB R8,[R9]stopMOV R0, #0x18 ; 程序结束返回编译器调试环境LDR R1, =0x20026SWI 0x123456;求字符串长度 输入R1 字符串起始地址 返回R3长度
length ADD R3,R3,#1 ;R3++LDRB R2, [R1,#1]! ; 将R1+1指向的单元内容加载到R2中 先前1位搜索CMP R2, #0 ; 检查R2的值是否等于0BNE length ; 如果不等于0,那么转到length处执行 MOV PC, LR ; 子程序返回 ;比较字符串是否相等;输入R1 str1的地址 R4 str1的长度 R2 str2的地址 R5 str2的长度;输出 R8 比较结果 ;0表示不一样 1表示一样
compare ;比较长度是否相等CMP R4,R5MOVNE R8,#0MOVNE PC, LR ; 子程序返回 MOV R4,#0 ;作为计数
loop LDRB R6,[R1],#1 ;R6遍历str1LDRB R7,[R2],#1 ;R7遍历str2 CMP R6,R7 ;字符不相等MOVNE R8,#0 ;即字符串不相等MOVNE PC,LR ; 子程序返回 ADD R4,R4,#1 ;计数器CMP R4,R5 ;控制循环次数BNE loopMOV 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, READONLYENTRY
start;想实现数组拷贝 需要输入原数组 数组长度 输出目的数组 即可;这里借用字符串拷贝 要求源数组最后加一个无效元素0 中间不能出现0LDR R1, =src0 ; R1指向数据区的源字符串LDR R0, =src ; R0指向数据区的目的字符串BL strcopy ; 调用子程序strcopy,完成字符串拷贝LDR R1,=src ; (右指针)R1起初指向src第一个单元 MOV R2, #0 ; 用于外层循环控制计数器,并初始化为0LDR 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 ; 外层循环控制计数器加1SUB R1, R1, #4 ; 右指针R1向左指针方向移动4字节CMP R2, R4 ; 是否全部扫描 BNE outer ; 没有完成全部扫描,继续外循环
stopMOV R0, #0x18 ; 程序结束返回编译器调试环境LDR R1, =0x20026SWI 0x123456strcopy LDR R2, [R1], #4 ; 将R1指向的单元内容加载到R2中STR R2, [R0], #4 ; 将R2中的数存储到R0指向的单元中CMP R2, #0 ; 检查R0的值是否等于0BNE 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 10AREA BlockData, DATA, READWRITE
src DCD 18,4,2,35,3,20,1,23,12,21,0 ;Keil会把此数组初始化为0END
结果分析
分析过了:略
4 factorial
流程图
代码编写
AREA factorial, CODE, READONLYENTRY
start;迭代算法思想 把每个阶乘放到数组中 接着求和 避免阶乘的重复计算
;1!=1
;n!=n*(n-1)!LDR R0,n ; R0是nLDR R1,=1 ; R1是计数器 1->nLDR R2,=nums ; R2指向numsSTR R1,[R2] ;放入1!ADD R1,R1,#1 ;从2开始
loopLDR R3,[R2] ;R3=(n-1)!MUL R4,R1,R3 ;R4=n*(n-1)!STR R4,[R2,#4]!; ;存入ADD R1,R1,#1 ;R1++CMP R1,R0BLS loopLDR R0,n ; R0是nLDR R1,=1 ; R1是计数器 1->nLDR R2,=nums ; R2指向nums LDR R5,=sum ; R5指向sumLDR R6,=0 ; R6存入sum
sumloopLDR R3,[R2],#4 ;R3取出遍历数组的值 ;R3=[R2++]ADD R6,R6,R3 ;R6+=R3ADD R1,R1,#1 ;R1++CMP R1,R0BLS sumloop STR R6,[R5] ;存入stopMOV R0, #0x18 ; 程序结束返回编译器调试环境LDR R1, =0x20026SWI 0x123456AREA BlockData0, DATA, READONLY
n DCD 4AREA BlockData, DATA, READWRITE
nums DCD 1,2,3,4,5,9,8,7,6,0 ;Keil会把此数组初始化为0
sum DCD 0END
结果分析
当n=4时
求阶乘
01 02 06 18
阶乘求和
01+02+06+18=21
当n=10时
0x003D9D19=4037913
5 略
最后
2023-4-14 23:40:30
你对我百般注视,并不能构成万分之一的我,却是一览无余的你。
祝大家逢考必过
点赞收藏关注哦