实验目的与要求

实验目的:

(1)掌握处理器仿真工具LC-3软件的安装和使用方法。

(2)学会在LC-3仿真环境下编辑程序和转换成可执行目标程序的方法 。

(2)学会在LC-3仿真环境下运行和调试程序的方法 。

实验要求:

(1)安装LC-3仿真器

(2)利用LC3EDIT输入机器代码程序(0/1模式)并创建创建可执行目标程序。

(3)利用LC3EDIT输入机器代码程序(hex模式)并创建创建可执行目标程序。

(4)利用LC3EDIT输入汇编代码程序并创建创建可执行目标程序。

(5)利用仿真器运用对应目标程序。

(6)学习和掌握断点,单步执行等调试方法和手段。

实验内容

LC3WinGuide:

​ 通过chapter1-3学习和掌握仿真器的使用。

​ 完成chapter4: P15 example1

​ P20 example2

实验过程与步骤

0x01 安装LC-3仿真器

运行”仿真器” 目录下的LC301.exe文件,点击unzip即可

0x02 输入机器or汇编代码

编译程序

输入一段01二进制程序,然后选择File -> save,保存文件,这里我命名为EX1.bin,接着选择Translate -> Convert Base 2,二进制编译模式。

img

同理,输入16进制机器码也可以,选择Translate->Convert Base 16编译,保存时的文件后缀必须为.hex。

输入汇编代码的话,文件保存为.asm后缀的文件,选择Translate->Convert assemble编译。

编译成功后,显示0个error,然后就能正常生产EX1.obj

img

运行安装目录下的Simulate.exe文件,出现主窗口和console 窗口( console 用于模拟输入和输出设备)

选择File -> Load Program,选择刚才编译好的汇编代码EX1.obj

img

这里的主窗口显示了编译后的汇编代码,还有他们的起始地址等等信息

img

运行和调试程序

选择 Execute ->run 运行程序,然后console窗口会给出运行结束的信息

这里箭头指向的单步调试按钮,然后红方框里显示着当前各种寄存器的状态,单步调试时可以观察寄存器变化来帮助理解汇编代码

img

除了单步调试,这里还有单步跳出,单步进入等功能,不一一列举了。

0x03 实战之完成example1

img

编译这段实现乘法的代码,求得R4 * R5的结果并放在R2中

我将这段代码保存为mul.bin,编译后得到mul.obj,加载进仿真器里。

接着再halt处下一个断点,防止程序跑完,然后就可以通过Set Value来设置初始寄存器的值,在本例中设置R4和R5的值,不用设太大防止陷入长时间循环。

我在这里设置为R4 = 3和R5 = 2

img

如图,成功将R4和R5自定义设置,接下来就可以用上个步骤里学习过的单步调试等技术来测试这个程序。

01单步调试法

Step over一次一次执行,同时观察寄存器的变化,由于初始值设置得较小,该方法调试的过程并不长。

02一键运行

之前在halt设置的断点现在派上用场,直接run program

img

仿真器会提示我们PC,即指向下一条指令的地址,是我们设置的断点处。

03 循环内设置断点

RUN一次能跑完一次循环,帮助我们分析每次循环带来的寄存器变化。

04 分析程序

img

不管用哪种调试方法,都能发现,程序出错了,2*3的结果得到9,很容易发现是循环多跑了一次,原因是如下指令:

0000 011 111111101 ;如果结果>=0 转移至x3201

当R5 = 2时,循环会执行三次,分别是R5为2,1和0时。

这里将条件跳转的三个条件码设置改为001,结果为正数时跳转,R5为2时就只会循环2和1两次了。

img

修改完后正确得到结果R2 = 6

0x04 实战之完成example2

第二个实验和第一个实验一样,编译以下源码

1
2
3
4
5
6
7
8
9
10
11
12
.ORIG x3000
TRAP x23 ;the trap instruction which is also known as "IN"
ADD R1,R0,x0 ;move the first integer to register 1
TRAP x23 ;another "IN"
ADD R2,R0,R1 ;两个整数相加
LEA R0,MESG ;载入字符串的地址
TRAP x22 ;输出字符串
ADD R0,R2,x0 ;sum保存到R0中,并准备输出
TRAP x21 ;显示结果
HALT
MESG .STRINGZ “The sum of those two numbers is”
.END

加载运行,不难发现程序又出错了,原因是trap读入的值是以字符串的形式读入,若我要实现一个3+4=7,输入3会存储为0x33,而4则是0x34,两者相加得到0x67,是ASCII表里的字符g。

修改方法则是在数字相加前先各自减去0x30,然后相加后再加上0x30。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.ORIG x3000
LD R6, ASCII
LD R5, NEGASCII
TRAP x23 ;输入
ADD R1,R0,x0 ;将第一个整数传给R0
ADD R1,R1,R5 ;将第一个ASCII数字转换成数值
TRAP x23 ;另一个驶入
ADD R0,R0,R5 ;将另一个ASCII数字转换成数值
ADD R2,R0,R1 ;将这两个整数相加
ADD R2,R2,R6 ;将和转换成ASCII表示
LEA R0,MESG ;载入字符串的地址
TRAP x22 ;输出字符串
ADD R0,R2,x0 ;结果传给RO
TRAP x21 ;显示结果
HALT
ASCII .FILL x30 ;mask:转换成ASCII
NEGASCII .FILL xFFD0 ;mask:-x30
MESG .STRINGZ "The sum of those two numbers is "
.END

编译这份修改后的源码。

img

成功得到正确的结果。

浅浅分析一下,这份源码修改后的源码分别在R6和R5加载进ASCII和NEGASCII处的值,用来实现字符和数字的转换(加减0x30)

实验结论或体会

初步掌握了LC3仿真器的使用,学会了调试和看寄存器。

初步掌握了LC3代码编译器的使用。

通过两个example学会了初步用调试功能分析LC3汇编程序。