本系列所有博客,知识讲解、习题以及答案均由北航计算机学院计算机组成原理课程组创作,解析部分由笔者创作,如有侵权联系删除。
从本节开始,课程组给出的教程中增添了很多视频讲解。为了避免侵权,本系列博客将不会搬运课程组的视频讲解,而对于文字讲解也会相应地加以调整,重点在于根据笔者自己的理解给出习题的解析。因此带来的讲解不到位敬请见谅。
这里先提供 Mars 使用的文本资料,如果视频上有不清楚的地方可以拿来参考:
中文、精简版:MIPS-C 指令集
英文、完整版:MIPS32 Architecture For Programmers
Mars 官网链接:http://courses.missouristate.edu/kenvollmar/mars/tutorial.htm
MARS 的全称是 MIPS Assembler and Runtime Simulator,是一个轻量级的、用于教学的 MIPS 汇编语言集成开发环境(IDE)。它由密苏里州立大学开发,基于 Java 环境运行,完全绿色且免费。我们的课程即使用此软件来进行 MIPS 汇编语言的学习、编写和运行。
(1) MARS 是支持 MIPS 汇编的编辑器,和我们的设计的 CPU 相同。
(2) 无论是正常程序还是异常处理程序,Mars 上都能很好的运行。
(3) MARS 的 Help 文档中,对指令,伪指令,系统调用等各种功能都有详细的介绍与使用样例,便于查阅使用。
(4) 最重要的是,Mars 中的指令都是在他内部的 CPU 模型上运行的,不论单周期还是流水线,他内部的 CPU 模型都是我们实验设计的黄金校验模型,对我们的 CPU 设计有很大的指导作用。
在第二章我们已经提到了,测试程序能够很好的检测我们 CPU 程序的正确性。而 MARS 就是负责运行和调试测试程序,导出 CPU 需要的机器码,并向我们展示正确的运行结果。
MARS 本体是一个 .jar 文件,需要 Java 环境运行。如果本机已经配置好了 Java 环境,则下载完成后可以直接双击运行。下载地址:http://courses.missouristate.edu/KenVollmar/MARS/download.htm
配置 Java 运行环境
JAVA_HOME
,变量值为你的 JDK 安装路径。修改【系统变量】中的变量 path
的值,在最前面加上: %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
。在【系统变量】中新建变量 classpath
,变量值为 %JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar
。上述几个变量设置在系统变量或用户变量里均可。具体细节见《Mars 使用教程》文档
MARS 的整体界面如所示。其分为若干个部分,下面将分别讲一下各部分的应用。
此处用于程序自身的基本操作及我们编写的汇编程序的运行、调试。
最上面一排为菜单栏,如图 3。其中,「File」用于开启新文件、打开旧文件、保存、另存为、关闭和导出程序等功能。「Edit」用于撤销、重做、剪切、复制、粘贴和查找替换。这两部分和大部分文本编辑软件是相同的。
正如大部分 IDE,MARS 也有一个用于书写代码的编辑器。我们的程序即写入这一区域。
在「Settings」→「Editor」中可以设置编辑器的字体类型、字体大小和语法高亮等。
在编辑器的下方有一个复选框,可以选择是否显示行号。
屏幕的下方就是信息区,它有两个选项卡:Mars Message 和 Run I/O。Run I/O 用于显示程序运行时的命令行输出,或者你也可以在这里对程序进行输入。Mars Message 选项卡用于显示其他信息,例如编译或运行时错误,以及其他一些有用的信息。当它显示编译错误时,你可以点击相应的信息来选中编辑器中对应的代码。
MIPS 寄存器在所有时候都会显示,即使是你没有在运行程序的时候。当你编写你的程序的时候,你可以参考这一区域来使用各个编辑器的名称,或者知道他们的常用用法(将鼠标悬停在上面就可以看到)。这里有三个选项卡:「Registers」(32 个通用寄存器,加上 HI、LO 和 PC 寄存器)、 「Coproc 1」(浮点数寄存器)、「Coproc 0」(一部分 CP0 寄存器,和中断、异常有关)。
当你点选「切换编辑与运行选项卡」中的「Execute」后,或者当你的程序编译成功后,会切换至运行界面。如下图所示:
当程序编译成功之后,寄存器会被初始化。运行窗口分为两部分:代码段(Text Segment)窗口和数据段(Data Segment)窗口。事实上还有第三个窗口:标签窗口(Labels),这需要我们选择「Settings」→「Show Labels Window」来显示。
数据段下方的左右箭头按钮用于翻页,下拉选单用于直接定位至某些关键位置。右侧的两个复选框用于选择以十进制还是十六进制表示内存的地址和值。
新建文件(Ctrl+N): 菜单栏 File -> New
打开文件(Ctrl+O): 菜单栏 File -> Open
保存文件(Ctrl+S): 菜单栏 File -> Save
延迟槽: 菜单栏 Settings -> Delayed branching
P5 后会使用,在学习延迟槽的具体原理前请勿勾选
初始地址设置:菜单栏 Settings -> Memory Configuration
为了适应自动评测的需要,请务必将初始地址设置为下图所示状态:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mde0V6yr-1645451625316)(https://cscore-buaa-edu-cn..buaa.edu.cn:8118/tutorial/mips/mips-3/assets/mips_3_3_5.png)]
官方帮助文档(F1): 菜单栏 Help -> Help
MIPS->Basic instructions: 基本指令的格式以及简介
MIPS->Extended (pseudo) instructions: 扩展指令的格式以及简介
MIPS->Directives: 伪指令的格式以及简介
MIPS->Syscalls: 系统调用的使用方法
MARS->Command: 命令行操作规范(会在 P7 中使用)
MARS 自带的界面笔者自己实在不敢恭维,各个栏目字体都很小,而且 jar 版本还无法调整除编辑栏以外其他栏目的字体大小,对眼睛伤害极大。但 MARS 毕竟还是要伴随我们一个学期,还是需要尽自己所能把 MARS 变得更适合我们使用。
菜单栏选择 Settings->Editor 进入编辑器设置,如下是笔者的设置供同学们参考。
对编写调试完成的代码进行导出操作时,应该选择下面哪个按钮?______(在空格中填入对应选项的大写字母,不要包含空格等其他任何字符)
答案:C
在MARS中,数据、正常程序代码、异常处理程序代码等都是分开存放于内存的不同区域中,而这些区域的划分是通过下面菜单栏中哪个选项进行设置的?
A. Settings -> Delayed branching
B. Settings -> Editor
C. Settings -> Memory Configuration
D. Tools -> Memory Reference Visualization
答案:C
在使用MARS编写汇编程序的过程中,我们经常会查看Mars中的帮助文档,如下图。
假如我们想要查看系统调用的使用介绍,我们应该选择哪一栏呢?
A. Basic Instructions
B. Directives
C. Syscalls
D. Exceptions
答案:C
在后续的Project中,我们可能需要运行大量的汇编代码,以下用来控制每秒运行多少条指令的按钮是:__________(在空格中填入对应选项的大写字母,不要包含空格等其他任何字符)
答案:D
帮助文档的快捷键是
A. F1
B. F3
C. F5
D. F7
答案:A
单步运行的快捷键是
A. F1
B. F3
C. F5
D. F7
答案:D
在运行之前,我们需要让汇编器编译我们的程序。我们的程序的内存中的数据和代码都存储在内存中,各个部分的存储位置(在内存中的地址)需要我们来指定。点击菜单栏中的「Settings」→「Memory Configuration」,弹出如图 5 的窗口,其中有三种设置可供我们选择。左侧的选择框即用来选择使用何种配置,右侧写明了具体的各个关键位置在此种配置下的具体位置。选中想使用的配置后,即可点击「Apply and Close」来应用配置并关闭窗口。
在程序运行之前,一定要检查配置是否与预想的相同。在我们的实验中,使用 Compact,Data at Address 0 这个配置。
在工具栏的中右侧有 6 个运行按钮,他们的功能为:
除此之外,MARS 还可以控制程序运行的速度,控制的滑动条就在工具栏的最右侧。如图,通过左右滑动其来调整每秒运行的指令数。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eW3zBZyJ-1645451625329)(# MARS 简介.assets/MIPS_button4-164545033768417.png)]
由于软件方面的原因,在运行时可能会遇到些 bug,这时重新编译运行即可。
前文已经讲了寄存器和内存窗口的位置,在程序运行的过程中,我们可以从这些窗口看到寄存器和内存的相应变化。
当程序运行至影响到相应寄存器或内存的指令时,MARS 会令响应的寄存器或内存地址高亮,以方便我们查看。如下图:
延迟槽是流水线 CPU 的重要知识点,并不在本讲的范围内,所以这里只会讲到 MARS 中延迟槽的设置与使用。
延迟槽是个可选设置,需要打开才能有效。打开方式为:「Settings」→「Delayed branching」,打上勾即为打开延迟槽。
当打开延迟槽运行程序时,在执行跳转指令后,程序不会立刻跳转,而是先执行完跳转指令的下一条指令,再进行跳转。这个所谓的跳转指令的下一条指令即为延迟槽,在运行时,其在代码段窗口中的高亮不是普通的黄色,而是绿色,如下图:
和许多其他的 IDE 一样,MARS 可以很方便地设置断点来进行调试。当程序运行到断点后会停下,等待我们的指示来进一步执行,此时便可查看程序的运行情况是否与预想相同。
当我们设置好断点后,点击运行按钮,程序会运行至下个断点处停止。
设置断点的方法很简单。编译完程序,跳转至程序运行界面后,在代码段窗口的左侧的一列(Bkpt)复选框即用来设置断点。在你希望停下的行的响应的复选框上点上勾,即为该行设置上了断点,如下图:
单步执行时一种常用的调试方式,每运行一部都观察一下寄存器和内存的值是否和期待的相同,从而判断出哪里出错。通常和断点配合起来使用。
为了便于调试和设置初值,我们可以选中某个寄存器或内存中的某个地址,左键双击就可以手动设置它的值,如下图:
对于我们编写的汇编程序,每个标签下的那块代码段一般都负责一部分功能,我们在设置断点调试程序时也大都是按照功能模块进行分块调试。
下面是一个求前12个Fibonacci数的一个程序
假如我们对它进行初步调试,应该在哪几行设置断点比较合理呢?
A. 14,26,31
B. 15,27,32
C. 7,15,27,32
D. 11,24,31,37
答案:B
在之后的P7中,我们需要完成中断异常处理,而这一处理需要用到CP0寄存器,这是不同于32个基本寄存器的,请在mars中找到该寄存器,并且初值不为零的是:
A. $8
B. $12
C. $13
D. $14
答案:B
在MARS中执行以下三行代码
li $t0, 0x12345678
li $t1, 0x7fffffff
add $t2, $t0, $t1
请问在执行第三行时,寄存器的值发生了什么样的变化?(在本题中,请设置MARS的Memory Configuration为Compact,Data at Address 0)
A.
$t2 0x0 -> 0x82345677
B.
$t2 0x0 -> 0x82345678
C.
CP0 $12 0x0 -> 0xff13
CP0 $13 0x0 -> 0x30
CP0 $14 0x0 -> 0x3010
D.
CP0 $12 0xff11 -> 0xff13
CP0 $13 0x0 -> 0x30
CP0 $14 0x0 -> 0x3010
答案:D
观察MARS的初始界面,以下哪些寄存器在初始时,里面储存的值不为0(多选):
A. $gp
B. $sp
C. $fp
D. $ra
答案:AB
在MARS中,如果想要设置延迟槽,应该通过下面菜单栏中哪个选项进行设置?
A. Settings -> Editor
B. Settings -> Memory Configuration
C. Tools -> Memory Reference Visualization
D. Settings -> Delayed branching
答案:D
在计组实验中,我们使用 MARS 编写汇编程序的目的是让汇编程序运行在我们的 CPU 中,同时用MARS 来验证程序运行结果的正确与否。因此,我们需要从 MARS 中将代码(机器码)导出,以导入我们的 CPU 中。
导出的步骤如下:
选择想要导出的数据范围(代码段 .text
或数据段 .data
),和导出格式(对于代码段一般我们选择 Hexadecimal Text),点击 Dump To File,选择保存文件名和地址即可导出,如下图。
上文所述的导出功能,只能对 .text(0x00003000-0x00003024) 和 .data(0x00000000-0x00000ffc) 这两部分内存进行导出。而在我们的实验中,还需对其他部分进行导出,例如异常处理程序,位于 .ktext(0x00004180-0x00004ffc)。
为了解决这个问题,MARS 提供了一个解决方案——命令行操作。使用命令行可以让你自己设定你所需要的导出内容。
MARS 提供了详细的文档来指导如何使用命令行。
导出中断处理程序,命令如下:
java -jar E:\Mars4_5.jar a db mc CompactDataAtZero dump 0x00004180-0x00004ffc HexText E:\code_handler.txt E:\source.txt
解析:
E:\Mars4_5.jar
是 MARS 的文件路径
a db mc CompactDataAtZero dump
这些参数的功能请自行查阅帮助文档
0x00004180-0x00004ffc
是需要导出的地址范围
HexText
表示导出的是 16 进制码
E:\code_handler.txt
是 16 进制码输出文件路径
E:\source.txt
是源文件路径
同学们请根据自己文件路径和需要将上述部分根据自己的情况进行更改,如果想进一步了解 Mars 的命令行操作,请参考 MARS 官方文档中 MARS -> Command 部分。如果同学们有兴趣可以尝试编写 bat 脚本文件,免去每次导出都要敲一串命令行指令的痛苦,这部分留作自学内容,请大家自行上网搜集资料进行学习。
按照我们要求设置好各数据段的初始地址,即选择Compact,Data at Address 0这个选择后,正常代码导出时的导出范围是?
A. 0x00000000 - 0x00000ffc
B. 0x00003000 - 0x00003ffc
C. 0x00400000 - 0x0ffffffc
D. 0x00003000 - 0x00003000+(n-1)*4 n为指令的个数
答案:D
如下图,是一个程序运行时的截图,问:代码导出时导出的是哪一列数据?
A. Address
B. Code
C. Basic
D. Source
答案:B
之前我们在ISE的教程中,已经学到了$readmemh指令,那么如果要从mars中导出能被这条指令读取的机器码,应该选择哪一选项?
A. ASCII Text
B. Binary
C. Binary Text
D. Hexadecimal Text
答案:D
在导出代码和数据时,一般只能导出0x00003000-0x00003088和0x00000000-0x00000ffc这两段。对于其他部分,比如中断/异常处理程序的导出,就需要使用命令行进行操作了。 根据下面这条命令,回答后面的问题。(答案中不要有多余空格)
java -jar mars4_5.jar a db mc CompactDataAtZero dump 0x00004180-0x00004ffc HexText E:\exc.txt E:\eh.asm
答案:
(1) 0x00004180-0x00004ffc
(2) 16
(3) E:\eh.asm