《计算机组成原理与汇编语言程序设计》实验报告五 循环结构及子程序
一、实验学时
课堂2学时,课后2学时
二、实验目的
1) 通过实验掌握并加深对循环结构的理解。
2) 通过实验掌握循环程序的设计方法。
3) 通过实验学习子程序的定义和调用方法。
4) 通过实验掌握子程序、子程序的嵌套、递归子程序的结构。
5) 通过实验掌握子程序设计、编制及调试。
6) 通过实验熟练掌握DEBUG的常用命令,学会用DEBUG调试程序。
三、实验要求
1)做好实验预习,复习汇编语言各种伪指令的功能。
2)按照实验内容与步骤的要求,独立思考,认真仔细地完成实验。
3)截取各步骤截图,为源码写好注释,书写实验报告。
四、实验内容
1、编制在屏幕上显示九九乘法表的程序。
程序:
DATA SEGMENT
S2 DB ?
S1 DB ?
X DB 1
Y DB 1
S DB 0AH
FCH=2AH
FDH=3DH
FKG=20H
FHH=0AH
FHC=0DH
DATA ENDS
STACK1 SEGMENT STACK
DB 20H DUP(0)
STACK1 ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK1
START:MOV AX,DATA
MOV DS,AX
MOV CL,9
LL1:
PUSH CX ;将CL压入堆栈段
MOV CL,Y
LL2:
CALL L1 ;调用子程序L1
INC X
LOOP LL2
MOV X,1
INC Y
MOV DL,FHH ;输出换行和回车
MOV AH,2
INT 21H
MOV DL,FHC
MOV AH,2
INT 21H
POP CX ;从堆栈段中取出CL
LOOP LL1
MOV AH,4CH ;程序结束
INT 21H
L1 PROC ;计算X*Y=Z并且输出X*Y=Z的子程序
MOV DL,X
ADD DL,30H
MOV AH,2
INT 21H
MOV DL,FCH
MOV AH,2
INT 21H
MOV DL,Y
ADD DL,30H
MOV AH,2
INT 21H
MOV DL,FDH
MOV AH,2
INT 21H
MOV AL,X
MUL Y
DIV S
MOV S1,AH
ADD AL,30H
MOV DL,AL
MOV AH,2
INT 21H
ADD S1,30H
MOV DL,S1
MOV AH,2
INT 21H
MOV DL,FKG ;输出空格
MOV AH,2
INT 21H
RET
L1 ENDP ;子程序结束
CODE ENDS
END START
2、编制在屏幕上显示用*组成的三角形的程序。
程序:
DATA SEGMENT
N DB ?
FCH=2AH
FDH=3DH
FKG=20H
FHH=0AH
FHC=0DH
DATA ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATA
START:
MOV AX,DATA
MOV DS,AX
MOV AH,1 ;输入一位16进制数确定输出行数
INT 21H
CMP AL,39H
JBE L1
SUB AL,07H
L1:SUB AL,30H
MOV N,AL
XOR BX,BX
MOV DL,FCH
MOV CL,N
MOV DL,FHH ;输出换行和回车
MOV AH,2
INT 21H
MOV DL,FHC
MOV AH,2
INT 21H
LOP:PUSH CX
INC BL
MOV CL,BL
MOV DL,FCH
LOP2:MOV AH,02H
INT 21H
LOOP LOP2
POP CX
MOV DL,0AH
MOV AH,02H
INT 21H
MOV DL,FHC
MOV AH,02H
INT 21H
CMP BL,9
JZ L2
LOOP LOP
L2:MOV AH,4CH ;程序结束
INT 21H
CODES ENDS
END START
3、(选做)自行编写杨辉三角输出代码,补充重要操作注释,编译链接执行、详细记录各操作步骤并截图。
五、实验步骤
1、编制在屏幕上显示九九乘法表的程序。
(1)在桌面新建一个文本文件,然后将源代码复制粘贴到文本文件中,对应的文本输入界面如图5-1-1所示:
图5-1-1 文本输入界面
(2)源代码输入完毕后保存文本文件,然后将文本文件JJCFB.txt转变为JJCFB.ASM文件,对应的文件转化界面如图5-1-2所示:
图5-1-2 文件转化界面
(3)将JJCFB.ASM文件放到Dosbox挂载的目录下,对应的文件挂载界面如图5-1-3所示:
图5-1-3 文件挂载界面
(4)打开Dosbox然后用MASM对源文件进行汇编,让其产生JJCFB.OBJ文件,对应的语句输入界面如图5-1-4所示:
图5-1-4 语句输入界面
(5)运行结束后到对应的目录查看是否生成了自己需要的文件,对应的文件生成界面如图5-1-5所示:
图5-1-5 文件生成界面
(6)用LINK将.OBJ文件连接成可执行的JJCFB.EXE文件,对应的命令键入指令界面如图5-1-6所示:
图5-1-6 命令键入指令界面
(7)运行结束后到对应的目录查看是否生成了自己需要的文件,对应的文件生成界面如图5-1-7所示:
图5-1-7 文件生成界面
(8)在DOS状态下运行LINK产生的JJCFB.EXE文件,对应的文件运行结果界面如图5-1-8所示:
图5-1-8 文件运行结果界面
2、编制在屏幕上显示用*组成的三角形的程序。
(1)在桌面新建一个文本文件,然后将源代码复制粘贴到文本文件中,对应的文本输入界面如图5-2-1所示:
图5-2-1 文本输入界面
(2)源代码输入完毕后保存文本文件,然后将文本文件TRIANGLE.txt转变为TRIANGLE. ASM文件,对应的文件转化界面如图5-2-2所示:
图5-2-2 文件转化界面
(3)将TRIANGLE.ASM文件放到Dosbox挂载的目录下,对应的文件挂载界面如图5-2-3所示:
图5-2-3 文件挂载界面
(4)打开Dosbox然后用MASM对源文件进行汇编,让其产生TRIANGLE.OBJ文件,对应的语句输入界面如图5-2-4所示:
图5-2-4 语句输入界面
(5)运行结束后到对应的目录查看是否生成了自己需要的文件,对应的文件生成界面如图5-2-5所示:
图5-2-5 文件生成界面
(6)用LINK将.OBJ文件连接成可执行的TRIANGLE.EXE文件,对应的命令键入指令界面如图5-2-6所示:
图5-2-6 命令键入指令界面
(7)运行结束后到对应的目录查看是否生成了自己需要的文件,对应的文件生成界面如图5-2-7所示:
图5-2-7 文件生成界面
(8)在DOS状态下运行LINK产生的TRIANGLE.EXE文件,对应的文件运行结果界面如图5-2-8所示:
图5-2-8 文件运行结果界面
3、(选做)自行编写杨辉三角输出代码,补充重要操作注释,编译链接执行、详细记录各操作步骤并截图。
(1)使用汇编语言进行杨辉三角代码的编写,对应的杨辉三角代码以及代码注释如下所示:
MOV AX, DATAS ; 将数据段DATAS的段地址加载到AX寄存器中
MOV DS, AX ; 将AX中的段地址设置为数据段DS寄存器中的值,以便访问数据段的数据
LEA DX, TITL ; 将TITL的地址加载到DX寄存器中
MOV AH, 9 ; AH寄存器用来存储要执行的BIOS函数号,这里是9号--显示字符串
INT 21H ; 调用21H中断,执行显示字符串的BIOS函数
CALL IN_NUM ; 调用输入数字的函数,等待用户输入数字行数
MOV CX, X ; 将输入的数字存储在CX中
CMP CX, 0 ; 比较CX与0的值
JZ EXIT ; 如果相等,就跳转到EXIT标签处
CMP CX, 18 ; 比较CX与18的值
JA EXIT ; 如果CX大于18,就跳转到EXIT标签处
CALL CR_LF ; 调用显示回车换行的函数
CALL CR_LF ; 再次调用,进行跳过一行
M_LOP: ; 定义标签M_LOP,开始循环打印杨辉三角形
CX=1~18 ; 循环打印1到18行的杨辉三角形
LEA SI, tmp1 ; 将tmp1的地址加载到SI寄存器中
MOV BX, 0 ; 将BX寄存器的初始值设为0
CALL YangHui ; 调用打印杨辉三角形的函数,输出一行
CALL CR_LF ; 一行输出完毕后加一个回车换行
LOOP M_LOP ; 循环输出杨辉三角形,直到行数达到18行
EXIT: ; 定义EXIT标签
MOV AH, 4CH ; 将AH寄存器设置为4CH,用于退出程序
INT 21H ; 调用21H中断,执行DOS系统调用
YangHui: ; 定义YangHui过程,用于计算杨辉三角形
MOV AX, [SI] ; 将tmp1中的数据取出并加载到AX寄存器中
ADD AX, BX ; 将AX寄存器中的值与BX寄存器中的值相加,并将结果存储到AX中
MOV BX, [SI] ; 将tmp1中的数据再次取出并加载到BX寄存器中
MOV [SI], AX ; 将计算结果存储到tmp1中
JZ END_YH ; 如果AX中的值为0,则跳转到END_YH标签处
ADD SI, 2 ; 将SI寄存器的值加2,以便下次读取tmp1中的下一个数据
CALL PRINT_AX ; 调用输出结果的函数,将AX中的值在屏幕上显示出来
CALL SPACE ; 调用输出空格的函数,用于分隔杨辉三角形中的每个数值
JMP YangHui ; 跳转到YangHui过程的起始处,开始新一轮计算
END_YH: ; 定义END_YH标签
RET ; 终止函数并返回
IN_NUM: ; 定义IN_NUM过程,用于获取用户输入的数字
MOV X, 0 ; 将X全局变量的初始值设置为0
MOV CX, 2 ; CX寄存器用于表示要输入的数字位数,这里设为2位
IN_X: ; 定义IN_X标签,开始循环输入数字
MOV AH, 7 ; 将7号函数号赋值给
AL,用于获取用户键盘输入的字符
INT 21H ; 调用21H中断,等待用户输入
CMP AL, 13 ; 判断用户是否按下回车键
JE END_IN ; 如果是,跳转到END_IN标签处
CMP AL, '0' ; 检查输入的字符是否为数字
JB IN_X ; 如果小于'0',跳转到IN_X标签处
CMP AL, '9' ; 检查输入的字符是否为数字
JA IN_X ; 如果大于'9',跳转到IN_X标签处
MOV DL, AL ; 将输入的字符存储到DL寄存器中
MOV AH, 2 ; 将2号函数号赋值给AH,用于在屏幕上显示字符
INT 21H ; 调用21H中断,将输入的字符在屏幕上显示出来
MOV AL, DL ; 将输入的字符移动到AL寄存器中
SUB AL, '0' ; 将'L0'的ASCII码值从AL中减去,得到真正的数字值并将其存储到AL中
MOV AH, 0 ; AH寄存器设置为0,用于无符号除法
MOV SI, AX ; 将AX的值暂存到SI寄存器中
MOV AX, X ; 将X变量中的值加载到AX寄存器中
MOV BX, 10 ; 将10加载到BX寄存器中,用于将老数字乘以10
MUL BX ; 将AX的值乘以BX
ADD AX, SI ; 将SI中的值加到AX中,这也就是用户输入的数字
MOV X, AX ; 将AX中的值保存到X变量中
LOOP IN_X ; 继续循环,等待用户输入下一个数字
END_IN: ; 定义END_IN标签
RET ; 终止函数并返回
PRINT_AX: ; 定义PRINT_AX过程,用于将AX寄存器中的数值在屏幕上输出
PUSH BX ; 保存BX寄存器的值
PUSH CX ; 保存CX寄存器的值
PUSH DX ; 保存DX寄存器的值
MOV BX, 10 ; 将10加载到BX寄存器中,用于对十进制数进行求余数
MOV CX, 0 ; 将CX寄存器的值设置为0,用于记录位数
P_LOP1: ; 定义P_LOP1标签,开始循环求余数
MOV DX, 0 ; 将DX寄存器的值清空
DIV BX ; 将AX中的值除以BX,余数存储到DX中
INC CX ; 将CX寄存器的值加1
PUSH DX ; 将DX寄存器的值压入堆栈中,用于存储求得的余数
CMP AX, 0 ; 比较AX中的值与0的大小
JNZ P_LOP1 ; 如果AX不等于0,则继续循环求余数
MOV AH, 2 ; 将2号函数号赋值给AH,用于在屏幕上显示字符
P_LOP2: ; 定义P_LOP2标签,开始循环输出每一位上的数字
POP DX ; 将压入堆栈中的余数值弹出到DX寄存器中
ADD DL, '0' ; 将L0的ASCII码值加到DX寄存器中,将数字转为字符
INT 21H ; 调用21H中断,将DX中的字符在屏幕上输出
LOOP P_LOP2 ; 如果CX不等于0
(2)在桌面新建一个文本文件,然后将源代码复制粘贴到文本文件中,对应的文本输入界面如图5-3-1所示:
图5-3-1 文本输入界面
(3)源代码输入完毕后保存文本文件,然后将文本文件YHSJ.txt转变为YHSJ.ASM文件,对应的文件转化界面如图5-3-2所示:
图5-3-2 文件转化界面
(4)将YHSJ.ASM文件放到Dosbox挂载的目录下,对应的文件挂载界面如图5-3-3所示:
图5-3-3 文件挂载界面
(5)打开Dosbox然后用MASM对源文件进行汇编,让其产生YHSJ.OBJ文件,对应的语句输入界面如图5-3-4所示:
图5-3-4 语句输入界面
(6)运行结束后到对应的目录查看是否生成了自己需要的文件,对应的文件生成界面如图5-3-5所示:
图5-3-5 文件生成界面
(7)用LINK将.OBJ文件连接成可执行的YHSJ.EXE文件,对应的命令键入指令界面如图5-3-6所示:
图5-3-6 命令键入指令界面
(8)运行结束后到对应的目录查看是否生成了自己需要的文件,对应的文件生成界面如图5-3-7所示:
图5-3-7 文件生成界面
(9)在DOS状态下运行LINK产生的YHSJ.EXE文件,对应的文件运行结果界面如图5-3-8所示:
图5-3-8 文件运行结果界面
六、实验小结
1、问题和解决方法:
(1)实验问题:进入DEBUG中进行命令输入的过程中无法退出当前的指令页面。
解决方法:使用DEBUG的命令Q进行回车后即可实现当前页面的退出。
(2)实验问题:在使用DOSBOX的时候会出现程序无法启动的情况。
解决方法:程序无法启动,可能是因为程序缺少某些依赖项或者与其他程序发生冲突,重新安装程序后程序可以正常启动。
(3)实验问题:在打开DOSBOX的过程中程序出现了错误信息。
解决方法:是由于程序文件损坏或者缺失导致的,对自己的程序文件进行检查后发现内部的文件语句出现了一行多条汇编语言的情况,对汇编语句进行修改后错误消失。
(4)实验问题:程序在运行过程中较为缓慢。
解决方法:由于计算机的硬件配置不足所导致,关闭其他应用程序后程序恢复正常的运行速度。
(5)实验问题:在程序运行的过程中出现了程序运行崩溃的情况。
解决方法:由于程序与其他软件发生了冲突所导致,以管理员权限运行程序后对应的问题得到解决。
(6)实验问题:在程序运行的过程中出现了界面显示不正常的情况。
解决方法:由于程序分辨率与计算机显示器分辨率不匹配造成的,修改计算机的显示器分辨率以及程序的分辨率后问题得到解决。
(7)实验问题:在程序运行的过程中程序无法读取文件。
解决方法:由于程序不在当前的挂载目录下,将文件拷贝到程序的工作目录下后错误消失。
2、心得体会:
(1)在使用DOSBOX进行汇编语言的编程过程中会用到DEBUG命令,如果成功进入DEBUG后会显示提示符‘—’。
(2)程序的编辑可以是各种文本编辑器,EDIT、记事本等都可以,编辑完成保存为filename.asm放到asm或masm当前目录即可。
(3).lst 文件是列表文件,列表文件同时给出源程序和机器语言程序,从而使调试变得方便,但该文件可有可无,如不需要直接回车便可。
(4).crf文件是交叉符号表,该表给出了用户定义的所有符号,对每个符号都列出了将其定义的所在行号和引用的行号,并在定义行号上加上#号,同列表文件一样,交叉符号表也是为了方便调试,可有可无,如不需要直接回车便可。
(5)汇编过程中产生目标文件之后(.obj),但是目标文件用的是浮动地址,不能直接上机执行,必须使用连接程序将其转换成可执行文件(.exe)。
(6).map文件是列表分配文件,也称映像文件,它给出每个段在内存中的分配情况,此文件也可有可无,一般直接回车便可。
(7).lib文件是用户程序用到的库文件,如有包含,输入库名称便可,若无回车便可。
(8)在进行Debug和指令测试时,会遇到各种各样的问题。为了更好地总结和归纳这些经验教训,应该注意记录每一个问题以及相应的解决方案。可以记录在笔记本、电脑中,也可以整理成表格,以便后续查阅或与他人分享。
(9)在测试指令时,需要确保每一个功能都经过测试并且能够成功执行。对于最常用的指令,需要进行详细的测试,并结合实际应用场景来验证其正确性。
(10)循环结构和子程序是计算机程序设计中的重要技术,以下是相关的知识点。
(11)循环结构是程序中用来重复执行某一任务的结构。通常使用for、 while或do-while等关键字或语法实现循环结构。循环可以用于迭代计算、数据分析和逻辑控制等场合。
(12)在循环结构中,通常需要使用控制语句控制循环结构的执行。常见的控制语句包括break和continue等,它们用于控制代码执行流程,以实现循环和条件判断等操作。
(13)子程序是程序中实现某个特定功能的代码块,通常用于简化程序结构和重用代码。子程序可以分为函数和过程两种类型,函数有返回值,而过程则没有返回值。
(14)在程序中,可以通过函数调用或过程调用来实现调用子程序。子程序可以递归调用自身或其他子程序,以实现具有复杂功能的程序实现。
(15)循环结构和子程序在程序设计中的应用广泛,特别是在算法设计、数据分析和游戏开发等领域。通过循环结构和子程序的结合使用,可以提高程序的可读性、可维护性和复用性。
(16)循环结构和子程序是程序设计中的核心技术,需要熟悉它们的原理和实现方法,以适应不同的业务需求和应用场景。在实践应用过程中,需要注意代码规范、算法正确性和代码效率等问题,以保障程序的正确性和性能。
(17)在学习循环结构和子程序时,我深刻体会到了它们在计算机程序设计中的重要作用。循环结构是执行重复任务的关键,而子程序则是实现复杂功能和模块化设计的关键。学习这些概念和技术,会让代码逻辑更加清晰且易于实现,也提高了代码的可复用性和可维护性。
(18)在实践应用过程中,需要注意控制循环结构和子程序的执行流程,确保程序的正确性和高效性,同时,还要保持代码规范和结构清晰,提高代码可读性。
(19)循环结构和子程序是计算机程序设计的核心概念和技术,对程序开发和优化至关重要,我相信熟练掌握这些技术,可以让我处理程序问题时更加得心应手。