五、实验结果及分析
1、实验运行过程及分析
(1)菜单:
主要代码:
在输出菜单之前首先使用清屏效果,以下为清屏效果的源代码:
MOV AH,15
INT 10H
MOV AH,0
INT 10H
之后调用宏指令输出菜单,并调用选择输入子程序:
OUTPUT_AH_9 CATALOG_1
:
:
OUTPUT_AH_9 CATALOG_6
CALL INPUT_CHOICE ; 调用选择输入子程序
用BUTTON判断是否需要再次循环,比较BUTTON是否为1,如果输入ESC,则退出菜单循环结束程序,如果BUTTON为0,则循环输出菜单。
CMP BUTTON,1
JNE OUTPUT_CATALOG
(2)输入功能:
主要代码:
通过循环判断NAME_BUF[SI+2]中的值是否为回车,若不是,则将该名字传送到用来存储数据的空间NAME_GRADE_SAVE中。
LOOP_INPUT_NAME:
MOV AL, NAME_BUF[SI+2]
CMP AL,13
JE INPUT_GRADE
MOV NAME_GRADE_SAVE [DI][BX],AL
INC SI
INC BX
LOOP LOOP_INPUT_NAME
通过循环判断NAME_BUF[SI+2]中的值是否为回车,若不是,则将该成绩传送到用来存储数据的空间NAME_GRADE_SAVE中。
LOOP_INPUT_GRADE:
MOV AL,GRADE_BUF[SI+2]
CMP AL,13
JE AGAIN
MOV NAME_GRADE_SAVE[DI][BX],AL
INC SI
INC BX
LOOP LOOP_INPUT_GRADE
最后输出一个值进行判断,若值为”y”,则循环到输入名字之前再次输入名字,若值为”n”,则退出该输入子程序。
OUTPUT_AH_9 TIP_5
MOV AH,1
INT 21H
CMP AL,"y"
JE INPUT
CMP AL,"n"
JE INPUT_OUT
OUTPUT_AH_9 TIP_2
JMP AGAIN
(3)输出功能:
主要代码:
用2号功能依次循环输出名字,当判断下一个地址的值为’$’时停止输出;并在循环的同时使变量NAME _LONG的值自加1,以便之后输出空格。
LOOP_OUTPUT_NAME:
MOV AL,NAME_GRADE_SAVE[DI][BX]
CMP AL,'$'
JE LOOP_OUTPUT_NAME_END
MOV DL,AL
MOV AH,2
INT 21H
INC BX
INC NAME_LONG
JMP LOOP_OUTPUT_NAME
根据名字的长度确定应该输出多少个空格,并循环输出空格。
MOV AL,14
SUB AL,NAME_LONG
PUSH CX
MOV CX,0
MOV CL,AL
LOOP_KONGGE_1:
KONGGE
LOOP LOOP_KONGGE_1
用2号功能依次循环输出成绩的值,当判断下一个地址的值为’$’时停止输出;并在循环的同时使变量GRADE_LONG的值自加1,以便之后输出空格。
LOOP_OUTPUT_GRADE:
MOV AL,NAME_GRADE_SAVE[DI][BX]
INC GRADE_LONG
CMP AL,'$'
JE LOOP_OUTPUT_GRADE_END
MOV DL,AL
MOV AH,2
INT 21H
INC BX
JMP LOOP_OUTPUT_GRADE
根据成绩的长度确定应该输出多少个空格,并循环输出空格。
MOV AL,14
SUB AL,GRADE_LONG
PUSH CX
MOV CX,0
MOV CL,AL
LOOP_KONGGE_2:
KONGGE
LOOP LOOP_KONGGE_2
将变量MINGCI每次循环时自加1,并在输出完名字和成绩之后输出该变量作为名次。
MOV DL, MINGCI
MOV AH,2
INT 21H
INC MINGCI
(4)排序功能:
主要代码:
用循环求出每个成绩的长度,当执行到’$’时,停止循环。
LOOP_SIZE:
INC GRADE_LONG
INC SI
CMP NAME_GRADE_SAVE[BX][SI],'$'
JNE LOOP_SIZE
比较前一个成绩和后一个成绩,若前一个大于后一个,则跳转到交换结束(即不交换),若前一个小于后一个,则跳转到交换的程序。
MOV AL,GRADE_LONG
CMP GRADE_MAX_LONG,AL
JA COMPARE_END
JB SORT_SHORT_CHANGE
若输入的两个数相等,则依次从高位到低位一个一个进行比较,若前者比后者小,则交换,若后者比前者小,则不交换,若相等,则继续循环。
LOOP_COMPARE:
MOV AL,NAME_GRADE_SAVE[BX][SI]
CMP NAME_GRADE_SAVE[BX][DI],AL
JA COMPARE_END
JB SORT_CHANGE ;前者比后者小,交换
INC SI
INC DI
CMP NAME_GRADE_SAVE[BX][DI],'$'
JNE LOOP_COMPARE
JMP COMPARE_END
将SI和DI各减小10,指向名字的第一个位置,循环20次,将整个存储学生名字和成绩的单位全部依次交换。
SUB SI,10
SUB DI,10
MOV CX,20
LOOP_SORT_CHANGE:
MOV AL,NAME_GRADE_SAVE[BX][SI]
XCHG AL,NAME_GRADE_SAVE[BX][DI]
XCHG AL,NAME_GRADE_SAVE[BX][SI]
INC SI
INC DI
LOOP LOOP_SORT_CHANGE
2、运行结果
图1:(菜单和输入效果)
图2:(直接输出效果)
图:3:(排序程序运行后结果)
图4:(排序后输出结果)
图5:(求最大值输出结果)
3、心得体会
通过本次综合实验,我对汇编程序的操作指令有了更加细致的认识。由于本次实验的实验目的是完成一个学生成绩管理系统,因此需要实现对学生成绩的排序,这也是本次实验的难点之一。在进行排序时,必须要实现名字与成绩同时运动,虽然我们之前已经进行过对数字的冒泡排序,但那只是对数字进行交换,没有考虑姓名的同步性问题。在解决这个问题时,我的方法是用20个字节的存储单元来存储单个学生的个人信息,而当判断出成绩大小需要交换时,我将指针移到单个学生和他下一个学生的第一个单元,然后循环20次,直接将一整块信息都进行交换。
另外一个难点是对学生成绩输入的处理,因为本次实验的要求是不定位数成绩输入,我想到了两种思路,一种是常规思路,每输入一个数时,将临时存储单位temp(初值为0)中的数值乘10,再加上刚刚输入的那个数,这样的好处在于无论我输入多少个数,最终的结果一定与我实际想要得到的数相同。另一种思路是不将它转换成实际的数,而是将输入的数当作字符串处理,这样使输入输出变得更加简单了,但是当我在进行比大小的操作时就变得相对复杂了,因为我必须要首先比较两个数的长短,如果相等的话再从高位向低位依次比较大小,比两个数字直接比大小复杂了很多。
最后,通过本次综合实验,我真的学习到了很多,而且说实话我找错误和发现内存异常的能力变得更强了,这都得益于这次综合实验中遇到的问题和bug。总之,本次综合实验让我收获颇丰。