Lab03 Longest-duplicate-substring

Purpose

子字符串是字符串中至少出现一次的连续字符序列。重复子字符串是一种由相同字符组成的子字符串。例如,“aabbbc”的重复子字符串是“aa”,“bbb”和“c”。
给定一个字符串及其长度,计算出它最长的重复子字符串的长度。

condition:
请注意,(1<=N<=100) 将存储在 x3100 中,并且 的每个字符都存储在从地址 x3101 开始的连续内存位置。
您可以假设仅包含 a-z 和 A-Z。
任务:将输出、最长的重复子字符串存储在 x3050 中。
R0-R7 初始设置为零,程序应从 x3000 开始。

several examples:

Memory address x3050 x3100 x3101 x3102 x3103 x3104 x3105 x3106
example 1 RESULT=3 NUM=6 a a b b b c
example 2 RESULT=4 NUM=5 Z Z Z Z z
example 3 RESULT=3 NUM=6 a a b a a a

Principles

Key issues:

如何记录最长重复的数量

要记录最长的重复数量,我们对字符串进行分析,可以看出,任意一个字符串,我们取其具有连续相同子串的模式,在任一时刻可以看作三部分,如xxxyzzz、xxxyzyzwww等,即两部分连续重复子串间隔一部分不连续的子串,即任意时刻我们最多只需要两个变量分别保存最长长度以及当前统计的连续重复子串长度,当这个相同连续被打破即出现不同字符时,比较一下两个长度,取其较大值。所以统计相同字符数量时使用两个寄存器:R2,R3,R2记录最长长度,R3记录当前子串相同字符长度,当判断到不同字符时,R3停止记录,跳转至比较R2与R3的大小,取其较大值存至R3中,并将R3清零后继续向后读取字符串,直至结束。

如何判断两个字符是否相同

在使用其他高级语言编程统计重复字符时,通常会用到双指针进行记录,所以联系到汇编语言,我们可以使用两个寄存器R5、R6作为两个指针,初始时分别指向第一个字符和第二个字符,每次判断是否满足R5==R6,满足则当前长度+1并后移指针,否则说明两个字符不相同,当前长度不变并将指针后移,直至R6指向最后一个字符,程序也相应结束。

Flow chart:

#mermaid-svg-nqllEFNzBT7MpFKR {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-nqllEFNzBT7MpFKR .error-icon{fill:#552222;}#mermaid-svg-nqllEFNzBT7MpFKR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nqllEFNzBT7MpFKR .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-nqllEFNzBT7MpFKR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nqllEFNzBT7MpFKR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nqllEFNzBT7MpFKR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nqllEFNzBT7MpFKR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nqllEFNzBT7MpFKR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nqllEFNzBT7MpFKR .marker.cross{stroke:#333333;}#mermaid-svg-nqllEFNzBT7MpFKR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nqllEFNzBT7MpFKR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nqllEFNzBT7MpFKR .cluster-label text{fill:#333;}#mermaid-svg-nqllEFNzBT7MpFKR .cluster-label span{color:#333;}#mermaid-svg-nqllEFNzBT7MpFKR .label text,#mermaid-svg-nqllEFNzBT7MpFKR span{fill:#333;color:#333;}#mermaid-svg-nqllEFNzBT7MpFKR .node rect,#mermaid-svg-nqllEFNzBT7MpFKR .node circle,#mermaid-svg-nqllEFNzBT7MpFKR .node ellipse,#mermaid-svg-nqllEFNzBT7MpFKR .node polygon,#mermaid-svg-nqllEFNzBT7MpFKR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nqllEFNzBT7MpFKR .node .label{text-align:center;}#mermaid-svg-nqllEFNzBT7MpFKR .node.clickable{cursor:pointer;}#mermaid-svg-nqllEFNzBT7MpFKR .arrowheadPath{fill:#333333;}#mermaid-svg-nqllEFNzBT7MpFKR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nqllEFNzBT7MpFKR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nqllEFNzBT7MpFKR .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-nqllEFNzBT7MpFKR .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-nqllEFNzBT7MpFKR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nqllEFNzBT7MpFKR .cluster text{fill:#333;}#mermaid-svg-nqllEFNzBT7MpFKR .cluster span{color:#333;}#mermaid-svg-nqllEFNzBT7MpFKR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nqllEFNzBT7MpFKR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

yes
yes
no
no
yes
yes
no
no
R0<-mem[x3100]
R0<-R0-2
R1<-x3101
R5<-mem[R1]
R6<-mem[R1+1]
NOT R5<-R5
R5<-R5+1
R5<-R5+R6
if R5 == 0
R3<-R3+1
R0 <- R0-1
if R0<0
R1<-R1+1
R4<- NOT R3
R4<- R4+1
R4<-R2+R4
if R4<=0
R2<-R3
R3<-0
R2<-R2+1
mem[x3050]<-R2
HALT
R7<-R0+1
if R7==0
R3<-0

Procedure

初始化:R0存放字符串总长度,因为使用双指针比较字符,所以R0=R0-2作为循环的总次数,R1存放字符串的起始地址,R2,R3分别存放最大长度和当前长度,R5,R6分别记录前一个字符和后一个字符,作为双指针向前移动
循环:将R5与R6相减用于比较当前两个字符是否相等,相等则R3+1,不相等则跳转比较,令R2=max(R2,R3),再回到循环,判断循环计数R0是否满足R0>0,满足则R1+1,R5,R6对应+1,即向前读入一个字符进行比较,重复循环过程。
结束:R0<0时跳转至存储,存储之前需要再做一次R2与R3的比较,将最大值放入R2中,最后将R2的值存入x3050内存单元

Result

Debug:

过程中遇到的主要问题有:
对于下列两个样例

89:sdsdsdssssssssdsdsfdjkkkkkkkkkkdlslsjdfnnnnnsdswiejdjskjsfkdsfdfskdksknsnsjsndllbbbbbdfsd:10

92:sdsdsdssssssssdsdsfdjkkkkkkkkkkdlslsjdfnnnnnsdswiejdjskjsfkdsfdfskdksknsnsjsndllbbbbbdfsdddd:10

分别输出10 以及 13,结果如下图所示,两个样例最长的子串都应该是连续的10个k,两个样例的区别仅在于最后的ddd,然而输出结果却不同

在调试模式中发现,在处理最后的子串时R3由8变为9后,遇到了不同的子串却没有清零,而是继续增加,即由9到10


检查发现代码中对R3的清零操作仅当R2<R3时才进行清零,所以上述情况就是在特殊情况下R2==R3,但未正确清零R3,导致R3继续计数输出错误结果


所以上述代码应改为如下图所示:

并且,由于我的程序是通过检测到不同字符时,跳转至比较当前R3正在记录的长度与R2中记录的最长长度并取最大值存入R2中,所以在程序要结束时应该再比较一次,因为可能存最后结尾的子串是最长的重复子串的情况。

Judge:

在本地 LC3Tool \text{LC3Tool} LC3Tool调试完毕后,将代码整理如下:用于网站在线 lc3 \text{lc3} lc3评测

.ORIG x3000
LDI R0, NUM;
ADD R0, R0, #-2;循环次数
LD R1, DATA ; R1 is the pointer of the string
ADD R2, R2, #0;计数器
ADD R3, R3, #0;CHECK LDR R5, R1, #0;第一个字符LDR R6, R1, #1;第二个字符NOT R5, R5;     ADD R5, R5, #1;R5取反ADD R5, R5, R6;相加为0说明相同BRz CNT      ;BRnp CMP      ;CNT ADD R3, R3, #1  ;计数
LOOP ADD R0, R0, #-1 ;循环次数BRn BREAK       ;结束ADD R1, R1, #1  ;后移BR CHECK
CMP NOT R4, R3;     ADD R4, R4, #1  ;R3取反ADD R4, R2, R4  ;BRnz MAX         ;R2<R3AND R3, R3, #0  ;R3<-0BR LOOP         ;
MAX ADD R2, R3, #0  ;R2=R3    AND R3, R3, #0  ;R3<-0BR LOOP;
BREAK ADD R7, R0, #1 ;循环次数BRz CMP;ADD R2, R2, #1;     STI R2, RESULT
HALT
RESULT .FILL x3050
NUM .FILL x3100
DATA .FILL x3101
.END

评测结果如下,正常运行,输出正确。

ICS计算系统概论实验3—LC3汇编代码实现最长重复子字符串Longest-duplicate-substring相关推荐

  1. 实验四:汇编代码调用系统调用的工作过程

    钟晶晶 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 工作过程 以41 ...

  2. ICS计算系统概论LC3汇编实验Lab5—中断、递归解决汉诺塔问题

    Lab Purpose 完成用户程序的编写. 编写下面描述的键盘中断服务例程. condition: 用户程序: 汉诺塔的参数,记录为N,将用xFFFF初始化并存储在X3FFF内存中. 您的用户程序从 ...

  3. 【微机原理 实验】大小写字母的转换实验 (含汇编代码)

    实验八  大小写字母的转换实验 更多微机实验:https://blog.csdn.net/yxp189/column/info/39992 汇编语言-微机原理与接口技术-实验 注意:未经允许,请勿转载 ...

  4. 实验四:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    贺邦+原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验目的: 使用库函数 ...

  5. c++ 模板类实现堆栈实验报告_编译原理——小型类C编译器的设计和实现(生成8086汇编代码)之1:问题定义以及总体功能...

    前面花了两篇文章来介绍词法分析和语法分析,接下来才是比较有意思的部分--一个小型类C编译器的设计和实现(其实是编译原理的课程设计啦!~)我用的是python2.7.13+PyQt来做的...事实上,正 ...

  6. 微机原理-虚拟仿真实验-DAC0832数模电路汇编代码

    微机原理-虚拟仿真实验-DAC0832数模电路汇编代码 ;-------------------------------------- DATA SEGMENTMESS1 DB 'sawtooth Q ...

  7. [实验]-从汇编代码来看volatile关键字的作用

    ★★★ 个人博客导读首页-点击此处 ★★★ 环境aarch64的交叉编译器 我们将C语言翻译成汇编代码,来看volatile关键字的作用 我们先看一段C语言代码 void udelay(uint64_ ...

  8. 计算机系统 实验一 LC-3仿真器安装和使用

    这里写自定义目录标题 深 圳 大 学 实 验 报 告 课程名称: 计算机系统(1) 实验项目名称: 实验一 LC-3仿真器安装和使用 学院: 计算机与软件学院 专业: 计算机科学与技术 指导教师: 张 ...

  9. 通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

    实验目的: 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 实验过程: 通过vi程序进行编程: int g(int x) { return x + 3; } int f(int x) ...

最新文章

  1. 微软发布WP SDK8.0 新增语音、应用内支付等原生API
  2. SpringMVC 理论与实用技术(一) 简单、实用、易懂的几个实例
  3. HDU 5025:Saving Tang Monk(BFS + 状压)
  4. 2021 年最值得了解的 Node.js 工具(下)
  5. Drupal常用开发工具(一)——Devel模块
  6. 2019,燃烧的中国开源年
  7. 不懂算法的程序员不是好工程师!
  8. Illustrator矢量图形软件2022Mac版
  9. Xcode12 兼容iOS14 及下载链接
  10. Java随机产生中文昵称
  11. fiddler 抓包下载钉钉直播回放
  12. 神经网络的分类及其不同的应用场景
  13. 曾经,我们有一个芝麻大小的梦想
  14. PR预设 16个毛刺效果抖音故障特效视频转场PR预设V2版本
  15. 21年11月第二周 力扣每日一题记录
  16. 计算机ram代表,RAM是什么
  17. system32 下exe文件的作用
  18. mysql里一个中文汉字占多少字节数?
  19. 【学生管理系统】班级管理
  20. coreldraw 长方体_用coreldraw 11制作铅笔_coreldraw教程

热门文章

  1. 头条号三农领域原创视频日赚1000,自媒体领域选择哪个好?
  2. 水果店的连环营销方案,只用半天时间就收款53万,你敢信?
  3. 请收下!春节聚会装B指南!附研习社工作汇报(2020)
  4. Python之format格式化函数以及数字格式化输出规范
  5. 无风扇cpu测试软件,噪音为零!TT首款无风扇设计CPU散热器
  6. Linux 查看进程启动时间、运行时间
  7. 李永乐讲卷积神经网络,卷积神经网络最新进展
  8. Windows10 在 Win+R启用以管理员身份运行的选项
  9. 编译原理:LL(1)文法的First集跟Follow集
  10. 美国研究生计算机科学专业申请,留学美国研究生计算机科学专业申请建议