hnu计算机系统实验一-原型机
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
实验一主要是对原型机的一些实验,比较简单,我们助教验收时,主要让我们讲汇编代码的逻辑,清楚这个大致就可以了,我这次的验收等级是B,可以参考一下。(思考题除了第一问是自己做的,其他都是copy的学长的,所有这里就不放出来了)还有就是,ir的结果是当前命令运行后的结果,但是,si后的命令是下一条命令,可能在观察时不太方便。主机复制到虚拟机还有JDK-21的安装问题在3.1有解决,就是不清楚我写的清不清楚了,哈哈哈
提示:以下是本篇文章正文内容,下面案例可供参考
1实验项目一
1.1项目名称
原型机vspm1.0
1.2实验目的
(1)了解冯诺伊曼体系结构;
(2)理解指令集结构及其作用;
(3)理解计算机的运行过程,就是指令的执行过程,并初步掌握调试方法。
1.3实验资源
(1)冯诺伊曼体系的相关内容;
(2)《最小系统与原型机I》
2实验任务
2.1实验任务A
任务名称:初识原型机
2.1.1 按照实验步骤,运行a-inst.txt文件
首先,文件代码如下:
分析代码可知:代码功能为输入的数循环自减再相加,类似阶乘操作。
例如,输入5,则输出为5+4+3+2+1=15 。
(1)进入终端,使用cd vspm1.0进入目录;使用./vspm a-inst.txt来运行原型机1.0的模拟器,其中a-inst.txt为代码文件。
运行结果如下图所示:
(2)在运行后,提示将要执行的指令地址及内容,在本例中,提示要执行位于内存00000110处的指令“in R1”,即等待输入一个整数值。此时输入si则表示执行此指令,同时也可以输入其他的指令,使用help可以查看此模拟器支持的命令:
输入help后的界面如下:
(3)此时输入i r,可以查看各个寄存器的值,而输入x 6 0000则表示查看从0000开始的连续6个内存地址值,结果如图所示。


(4)输入si,则表示运行一条指令,例如此时运行的指令是“in R1”,表示等待输入,输入一个值5,在输入完成后将此数值存至R0寄存器,运行完成后,再运行i r指令,就可以看到输入的值5确实是已经存在R0寄存器中,每个寄存器的值都用十进制和十六进制表示,如下图所示。
(5)接下来执行”movi 1”,及将R0设置为1 。执行结果如下:

(6)然后是指令”add R2,R1” ,及将R1+R2的结果储存在R2。执行结果如下:
(7)然后是指令”sub R1,R0” ,及将R1-R0的值放入R1,等价于R1-- 。并且由于R1>1,G被设置为1 。
(8)然后是指令”movd” ,及将PC的值赋值给R3,此时PC=10,故R3为10 。
(9)然后是指令”movi -3” ,及将-3存储在R0中。
(10)然后是指令”add R3,R0” ,及将R3-3 ,目的是为了让后续的PC改为7,进行指令的循环。
(11)然后是指令”jg” ,及跳到第二行指令”movi 1”去执行,及循环操作。
(12)之后便是循环的过程,可以输入”c” ,让程序进行到底,其结果如下:
(13)输入”10” 的结果如下:

可见结果与分析的一致。
2.1.2 运行并调试 b-inst.txt ,并对这些代码所做的工作进行解释;
首先,代码文件如下:
分析代码可知,其功能为输入两个数,输出较小的那个数,及min(a,b)。
情况一:(5,3)
(1) 输入5
执行指令”in R1”,将a存进寄存器R1
(2) 输入3
执行指令”in R2” ,将b存进寄存器R2
(3)
执行指令”mova R0,R1” ,将a的值存入R0
(4)
执行指令”sub R1,R2” ,将a-b及R1-R2,并记录G的值,若G为1,则表示b小,则输出b;反之,若G为0,则输出a 。
(5)
执行指令”mova R1,R0” ,将a的值存入寄存器R1
(6)
执行指令”movd” ,及让R3=11
(7)
执行指令”movi 6” ,及让R0=6
(8)
执行指令”add R3,R0” ,让R3=17,为后续跳转做准备。
(9)
执行指令”mova R0,R2” ,将b的值存入R0 。
(10)
由于a>b, G=1,执行跳转指令”jg”,跳转到第12行指令。
(11)
输出b的值,接下来将进行停机指令。
情况一:(5,8)
(1)~(9)情况相同。
(10)
由于a<=b , PC不跳转,还是自加1 。
(11)
执行指令”mova R0,R1” , 将a的值存入R0 。
(12)
输出a的值,接下来执行停机指令。
总结:
由上述两种情况,也可分析出b-inst.txt 文件内代码功能为输出min(a,b) 。
2.1.3 运行并调试 c-inst.txt ,并对这些代码所做的工作进行解释;
首先,文件代码如下:
分析代码可知:代码功能为a*b,及乘法公式。
具体实现为:将a自己相加b次。及将b-1,循环b次,直至b=0 。
以(4,3)为例:
循环前的准备工作:
这里只阐述第一次循环过程:
(1)
执行至指令”sub R1,R0” ,功能为将b作为计数,进行-1操作。并记录G的值,实现循环。
执行至指令”movb R0,R1” ,是将寄存器R2作为累加的结果,并储存进内存02地址。
而由于G=1,因此,PC会进行跳转,从而进入循环;而进入最后一次循环时,b=1,并不>0 ,因此,会跳过循环,输出结果!
2.2实验任务B
任务名称:思考问题解答
(1) 如果基于这些指令实现两个整数的乘法与除法?
乘法:
c-inst.txt已经给出了正数乘法的汇编指令。这里,我给出非零整数的汇编代码,
我的基本思路是:先将a与b进行去负号操作,同时记录负数的个数,由于只有两个数,故个数只能有0,1,2三种可能,而只有个数为1时,结果才为负
代码如下:


运行结果如下:
两个负数:
两个正数:
先负后正:
先正后负:
但值得注意的是,由于寄存器仅有8位因此,当一个正整数大于128时,结果会溢出,可能显示负数。
除法:
与乘法类似,我们可以将a/b看成a-b-b···-b ,最后的余数一定小于b 。
下面,我编写了两种汇编指令,其一为正整数除法,其二为非零整数除法。
正整数除法:
汇编代码如下:
在结束循环之后,R3的值在-(b-1)~0之间,而当可以整除时,及余数为0,结果不需要调整;当不能整除时,及余数为负数,需要-1调整。
运行结果如下:
非零整数除法:
与非零整数乘法思路类似,先对a与b去负号操作,同时纪录负数的个数,若个数为1,则要取相反数处理。
汇编代码如下:



执行结果如下:
两负数:

两正数:


先正后负:

先负后正:

3总结
3.1实验中出现的问题
【分任务列出实验过程中出现的问题】
1、一开始在虚拟机中不能将主机文件复制到虚拟机。下载VMtools或者在终端中依次执行:sudo apt-get autoremove open-vm-tools , sudo apt-get install open-vm-tools , sudo apt-get install open-vm-tools-desktop,即可!
2、在运行时,显示java版本过低,在终端执行sudo apt install software-properties-common , sudo apt-get update , sudo apt-get upgrade , sudo apt-get openjdk-21-jdk即可 (这种方法适合64位虚拟机)
或者在java官网下载压缩文件夹,复制到/root/usr/local/src文件夹中,可以在终端执行:sudo nautilus打开系统文件夹,找到所在文件夹粘贴;在终端依次执行:
cd / , cd /usr/local/src , tar -xzvf openjdk-21-jdk.tar.gz (解压) , ln -s /usr/local/src/openjdk-21 /usr/local/src/jdk21(创建软连接) , cd , sudo gedit /etc/profile(如果报错,先执行sudo apt-get install gedit) (注意一定要加sudo,否则,没有权限保存profile修改的内容), 在文件尾添加:
export JAVA_HOME=/usr/local/src/jdk21
export CLASSPATH=./ J A V A H O M E / l i b / d t . j a r : JAVA_HOME/lib/dt.jar: JAVAHOME/lib/dt.jar:JAVA_HOME/lib/tools.jar
export PATH = J A V A H O M E / b i n : JAVA_HOME/bin: JAVAHOME/bin:PATH
然后在终端运行:sudo source /etc/profile (使配置生效) , 然后查看Java版本验证是否下载成功(java -version) 。
3.2心得体会
【真实感受】
1、首先,我学会了对虚拟机进行java环境的配置和基础操作。
2、了解了简单原型机的汇编指令执行的内容,学会了自己编写汇编代码来完成指定的算法功能。
3、也了解了从编译到汇编过程的实现,实现方法有很多,miniCC中便是先转为四元组,再转为汇编指令,但是这种操作在执行一些特定的算法时可能会出现汇编操作内容重复出现的情况,效率可能不是很好。
总之,这次的实验很有乐趣,我的收获也很丰富!
附件
正整数除法
in R1 #输入被除数a
movb R0,R1 #将a存入内存
in R1 #输入除数b
#循环开始
movi 1
add R2,R0 #将结果加1
movi 0
movc R3,R0 #取出被除数a
sub R3,R1 #a-b,并存储G的值
movb R0,R3
movi 9
mova R3,R0
jg
movi 0
movc R3,R0
sub R0,R3 #判断是余数是否小于0
movi 26
mova R3,R0
jg
out R2 #余数为0,直接输出
halt
movi -1
add R2,R0 #余数为0,需-1调整
out R2 #输出结果
halt #停机
非零整数除法
#预处理操作
in R1 #输入乘数a,6
movb R0,R1 #7
in R1 #输入被乘数b,8
movi 1 #9
movb R0,R1 #10
#将a与b取绝对值并记录负数的个数。
#先对a取绝对值
movi 0 #11
movc R1,R0 #将a取出,12
sub R2,R1 #如果是负数跳转,13
movi 20 #14
mova R3,R0 #15
jg #16
movi 7 #17
add R3,R0 #18
jmp #19
mova R1,R2 #20
movi 0 #21
movb R0,R1 #22
movi 1 #23
mova R1,R0 #24
add R0,R1 #25
movb R0,R1 #在02地址处存储负数的数量,26
#将寄存器和G初始化
movi 0 #27
mova R1,R0 #28
mova R2,R0 #29
mova R3,R0 #30
sub R3,R0 #31
#对b取绝对值
movi 1 #32
movc R1,R0 #33
sub R2,R1 #如果是负数跳转,34
movi 41 #35
mova R3,R0 #36
jg #37
movi 8 #38
add R3,R0 #39
jmp #40
mova R1,R2 #41
movi 1 #42
movb R0,R1 #43
mova R1,R0 #44
add R0,R1 #45
movc R2,R0 #46
add R2,R1 #47
movb R0,R2 #48
#将寄存器和G初始化
movi 0 #49
mova R1,R0 #50
mova R3,R0 #51
sub R3,R0 #52
movi -1 #53
mova R2,R0 #54
#循环开始
movi 1 #55
add R2,R0 #将结果加1,56
movc R1,R0 #取出除数b,57
movi 0 #58
movc R3,R0 #取出被除数a,59
sub R3,R1 #a-b,并存储G的值,60
movb R0,R3 #61
movd #62
movi -7 #63
add R3,R0 #64
jg #65
movi 0 #66
movc R3,R0 #67
sub R0,R3 #判断是余数是否小于0,68
movi 74 #69
mova R3,R0 #70
jg #71
movi 1 #72
add R2,R0 #73
#判断负数个数
movi 2 #74
movc R1,R0 #75
movi 1 #76
sub R1,R0 #77
movi 86 #78
mova R3,R0 #79
jg #两个负数情况,80
movi 0 #81
sub R0,R1 #82
jg #两个正数情况,83
sub R1,R2 #84
mova R2,R1 #85
out R2 #输出结果,86
halt #停机,87
正整数乘法
in R1 #输入乘数a
movb R0,R1 #将a存入内存00处
in R1 #输入被乘数b
#循环开始
movi 1
sub R1,R0
movi 0
movc R3,R0
add R2,R3
movd
movi -5
add R3,R0
jg #跳转
out R2 #输出结果
halt #停机
非零整数乘法
#预处理操作
in R1 #输入乘数a,6
movb R0,R1 #7
in R1 #输入被乘数b,8
movi 1 #9
movb R0,R1 #10
#将a与b取绝对值并记录负数的个数。
#先对a取绝对值
movi 0 #11
movc R1,R0 #将a取出,12
sub R2,R1 #如果是负数跳转,13
movi 20 #14
mova R3,R0 #15
jg #16
movi 7 #17
add R3,R0 #18
jmp #19
mova R1,R2 #20
movi 0 #21
movb R0,R1 #22
movi 1 #23
mova R1,R0 #24
add R0,R1 #25
movb R0,R1 #在02地址处存储负数的数量,26
#将寄存器和G初始化
movi 0 #27
mova R1,R0 #28
mova R2,R0 #29
mova R3,R0 #30
sub R3,R0 #31
#对b取绝对值
movi 1 #32
movc R1,R0 #33
sub R2,R1 #如果是负数跳转,34
movi 41 #35
mova R3,R0 #36
jg #37
movi 8 #38
add R3,R0 #39
jmp #40
mova R1,R2 #41
movi 1 #42
movb R0,R1 #43
mova R1,R0 #44
add R0,R1 #45
movc R2,R0 #46
add R2,R1 #47
movb R0,R2 #48
#将寄存器和G初始化
movi 0 #49
mova R1,R0 #50
mova R2,R0 #51
mova R3,R0 #52
sub R3,R0 #53
#循环开始
movi 1 #54
movc R1,R0 #55
sub R1,R0 #56
movb R0,R1 #57
movi 0 #58
movc R3,R0 #59
add R2,R3 #60
movd #61
movi -7 #62
add R3,R0 #63
jg #跳转,64
movi 2 #65
movc R1,R0 #66
movi 1 #67
sub R1,R0 #68
movi 77 #69
mova R3,R0 #70
jg #两个负数情况,71
movi 0 #72
sub R0,R1 #73
jg #两个正数情况,74
sub R1,R2 #75
mova R2,R1 #76
out R2 #输出结果,77
halt #停机,78
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)