《 汇 编 语 言》课程综合性实验报告
实验题目 | 显示学生名次表 | ||||||||||
一、实验目的 通过显示学生成绩名次表,进行汇编语言程序设计应用的综合性训练。综合运用汇编语言循环程序、子程序、宏指令编程方法,提高汇编语言程序设计能力的应用水平。 二、设备与环境 PC兼容机、Windows操作系统、汇编程序masm for windows 2012。 三、实验内容 1.实验内容: 编制一程序,要求接收从键盘输入的一个班的学生的学号、姓名、成绩,对学生的成绩进行排序,再按学号顺序和学生名次顺序分别把学生成绩显示出来。 2.实验要求: ①必须画程序流程图。 ②本程序要求要有多重循环和子程序及宏,其中成绩输入、计算学生名次、显示学生名次都分别用子程序,也可用宏处理。 ③要求用菜单选择,输入1时按学号顺序输出成绩(包括姓名、学号、成绩、名次),输入2时按成绩排名顺序输出成绩(包括姓名、学号、成绩、名次)。 四、实验结果及分析 1.主界面的设计与实现: (1)程序分为两个菜单: ①一级菜单:完成学生成绩的录入或从本地文件中载入学生成绩信息。(图 1-1 )用户输入对应选项1、2、3或L、C、E,分别执行相应的功能。 输入1(或 L ):表示从文件中读取学生成绩信息; 输入2(或 C):表示重新录入学生成绩信息,并保存到文件中; 输入3(或 E):表示退出程序。 ②二级菜单:完成对学生成绩信息的排序,并输出排序后结果。(图 1-2 ) 输入1:完成按学号排序(升序)并输出排序后结果; 输入2:完成按总分排序(降序)并输出排序后结果; 输入3:返回一级菜单。 图 1-1程序主界面: 图 1-2 程序二级菜单界面: 2.排序功能的实现: 图 1-2 输入学生成绩界面: 图 1-4 按总分排序输出学生成绩信息: 3.设计思路: (1)数据定义: 一个数据元素(一个学生的数据项)应该为一个结构类型,定义如下: STUDENT STRUC ; 定义学生结构体 LINK DW 0 ; 单链表指针,指向下一个节点偏移地址 ID DB '000' ; 学号 NAMES DB '$$$$$$$$' ; 姓名 CSCORE DB ? ; 语文成绩 MSCORE DB ? ; 数学成绩 SUM DB ? ; 总分 STUDENT ENDS 其中,LINK 字段为链指针,指向数据元素的后续地址,它占用一个字,其初值为 0;ID字段为3个字节,存放学号,为了输入输出方便,学号以3位十进制数字的字符存放;NAMES字段为 8 个字节,存放姓名,为了方便输出,预设8个‘$’符号;CSCORE字段、MSCORE字段和SUM字段分别为学生的语文成绩、数学成绩、总成绩,由于这3个字段的值不超过200,分别以一个字节的二进制存放即可。 每一个学生的数据信息为结构S这样一个数据元素。则 10 个学生需要分配10个这样的数据元素的存储单元。用上面的结构名 STUDENT 作为伪指令定义学生数组如下: S_ARRAY STUDENT 10 DUP(< >) ; 预设学生人数为 10 S_ARRAY 是一个结构类型的数组,它包括 10 个元素,每一个元素为一个 STUDENT类型的结构。 在建立链表的过程中,会用数组元素的首地址装填LINK字段,为了避免冲突,数组元素的首地址不能为 0 和 1 ,因此,在数据段定义中定义 S_ARRAY 数组之前,用 DW分配了一个字,使数组 S_ARRAY 的第一个元素的位移量不为 0,也不为 1。 (2)方法和步骤: 这个程序主要包括3个部分:输入数据、按学生的总成绩由高到低(降序)建立链表和按学生名次输出学生信息。 ①输入数据。 从数组的第一个元素开始,顺序填装数据元素,因此设置循环将S_ARRAY 数组第一个元素的位移量送至 BX,每一次循环,BX加上 TYPE S_ARRAY(值为 16),使BX指向S_ARRAY数组中下一个元素的起始地址。 装填每个元素的各字段值:输入学号存放到 S_ARRAY 数组元素的 ID字段;输入姓名、语文成绩、 数学成绩并分别存放到数组元素的 NAMES字段、CSCORE字段和MSCORE字段;将CSCORE字段和MSCORE 字段的值相加得到总成绩送入SUM字段。 ②按学生的总成绩由高到低进行排序建立链表。 这一部分任务是按学生总成绩由高到低进行排序。采用单链表方式,给数据元素的链指针 LINK 字段装填数据,使LINK字段指向它的后继数据元素。步骤如下: Ⅰ. 初始时,数组元素的每个LINK字段值为 0,表示数组元素没有被选中。扫描数组元素的SUM字段,从中到第一个最大的数,将这个数组元素设置为链表的头,保存这个数组元素的位移量,并将其LINK字段设置为 1,标记这个数组元素已被选中但尚未装填链指针。 Ⅱ. 扫描整个数组,从链指针字段为 0 的数组元素中寻 SUM 字段最大的数组元素,将这个数组元素的位移量填至上一个最大元素的LINK字段,并将 1 送至这个数组元素的LINK字段。 Ⅲ. 重复执行步骤 Ⅱ ,最后剩下一个链指针字段值为 1 的数组元素,该元素是链表的链尾。 ③ 按名次(总成绩由高到低的顺序)输出学生信息,也就是按链表中元素的顺序访问其数据元素。步骤如下: Ⅰ. 将链表的头元素的位移量送到 BX 寄存器。 Ⅱ. 输出BX 指向的数据元素的信息,即学号、姓名、语文成绩、数学成绩和总成绩,输出回车换行。判断 [BX].LINK 字段的值是否为 1,为1则结束程序,否则将该元素LINK字段的内容送入 BX中,重复步骤 Ⅱ。 4.流程图与关键代码分析: ①按学生总成绩排序(降序)流程图,同时建立单链表: ②按名次由高到低输出学生成绩信息子程序(即单链表方式顺序输出): 5.总结与体会: (1)程序主要完成功能: ①从键盘输入学生成绩信息,依次将学生的学号、姓名、语文成绩、数学成绩、总成绩(经过计算后),存放在对应数组元素的字段中。 ②按照总成绩从高到低排序,即完成单链表的建立,将单链表的头指针保存在 DX 寄存器中,在输出时从头指针开始遍历单链表。 ③按照学生总成绩的名次顺序(由高到低)输出学生成绩信息,即对②所建立的单链表的遍历,在初始时需要将单链表头指针(DX寄存器中存放)赋值给 BX,以便完成遍历输出。 (2)程序的实现: ①主要采用了结构数组,因为每一个项都具有相同的结构,因此先定义一个 STUDENT 类型的结构体,使用该结构体名作为伪操作指令定义n个相同的结构体类型的数组元素。在每一个数组元素中都包含一个 LINK 字段,初始值为0。 ②建立单链表,即完成对学生成绩信息的降序排列。 首先从所有数组元素中出总成绩最大的一项,将该数组元素作为单链表的头指针,保存在DX中,同时将LINK字段赋值为 1; 其次,从 LINK 字段为0的数组元素中到总成绩最大的一项,将该数组元素的偏移地址作为前一节点的LINK字段值,同时将该节点的 LINK 字段值置为 1; 重复上述步骤直到该结构体类型数组中的最后一个节点LINK字段置为1,该节点即为单链表的链尾。 ③遍历单链表,即对学生成绩信息按总成绩由高到低输出。 首先将单链表的头指针赋值给BX,依次循环 COUNT(学生人数) 次输出每一个数组元素的值,每次输出结束后,将 BX 的值加上 TYPE S_ARRAY(即加 16字节),BX指向下一个数组元素的首地址。 其次在输出每一个数组元素后,即循环的过程中必须同时满足两个条件:计数器CX != 0 且 [BX].LINK != 1 ,若有任意一个条件不满足则跳出循环。使用 LOOPNZ 指令即可实现。 ④对于将学生成绩信息保存到文件,以及从文件中读取学生成绩信息并输出,关于文件的打开、读取、写入、关闭,这一块相关功能并没有实现。 ⑤程序纠错功能较差,当用户输入错误后,没办法实现退格删除,重新输入,有待改进。 ⑥由于学生的姓名不定长,导致输出时对齐存在一定困难。 ⑦程序还可以继续优化,结合子程序与宏各自的优点,宏的调用速度块,可以用实元代替哑元的方式完成调用不同的子程序,以及灵活的传值,而子程序应该做到可以被多次调用,写的更为灵活、复用性高。 (3)收获和体会: 通过本次综合实验不仅提高了汇编语言程序设计的能力,也对高级汇编技术有了初步的认识与了解,如子程序与宏的配合使用。同时对于程序的算法,才是程序的核心,是程序设计的重点,根据对程序中数据的分析,采取不同的数据结构,结合优良的算法,可以大大提高程序的效率。对自己在以后的学习中更应该重视基础、把握重点,编程语言是工具,而算法、结构才是核心。只有结合良好的思想指导,熟悉利用工具才能做出好的软件。 源代码: CRLF MACRO ;回车换行宏定义 MOV DL,0DH MOV AH,02H INT 21H MOV DL,0AH INT 21H ENDM BLANK MACRO NUM ;空格宏定义 MOV CX,NUM CALL BLANK_PROC ENDM SHOW MACRO STRING ;显示字符串宏定义 LEA DX,STRING MOV AH,09H INT 21H ENDM STUDENT STRUC ;定义学生结构体 LINK DW 0 ;指针,指向下一个节点 ID DB '000' ;学号 NAMES DB '$$$$$$$$' ;姓名 CSCORE DB ? ;语文成绩 MSCORE DB ? ;数学成绩 SUM DB ? ;总分 STUDENT ENDS DATASG SEGMENT DW ? ;避免数组元素和 LINK 字段冲突 S_ARRAY STUDENT 4 DUP(<>) ;预设学生人数 NUMBER DW 0 ;键盘输入学生人数 COUNT EQU LENGTH S_ARRAY ;COUNT EQU NUMBER ;定义学生人数个数 COUNT ;==================菜单======================= MENU1 DB 0DH,0AH,0DH,0AH,0DH,0AH,0DH,0AH,0DH,0AH DB " ------------------MENU(Load OR Create)--------------------- ",0DH,0AH,0D,0AH DB " 1.Load the student information from an existing file (L)",0DH,0AH,0D,0AH DB " 2.Create a new file and write the student information (C)",0DH,0AH,0D,0AH DB " 3.Exit the student achievement management system (E)",0DH,0AH,0D,0AH DB " ----------------------------------------------------------- ",0DH,0AH,0D,0AH DB " Please Input Your Choice:",'$' MENU2 DB 0DH,0AH,0DH,0AH,0DH,0AH,0DH,0AH,0DH,0AH DB " ------------MENU(Display)-------------- ",0DH,0AH,0DH,0AH DB " 1.Sort by student ID ",0DH,0AH,0DH,0AH DB " 2.Sort by scores ",0DH,0AH,0DH,0AH DB " 3.Back to previous menu ",0DH,0AH,0DH,0AH DB " --------------------------------------- ",0DH,0AH,0DH,0AH DB " Please input your chioce:",'$' PRESS_KEY db 0dh,0ah,'Please press any key ','$' INPUT_NUMBER db 'Please input the number of students: ','$' INPUT_INFO db 0Dh,0Ah,'ID NAME Chinese Math',0Dh,0Ah,0Dh,0Ah,'$' OUTPUT_INFO db 'ID NAME Chinese Math SUM',0dh,0ah,0Dh,0Ah,'$' ;================菜单定义结束=============== DATASG ENDS STACKSG SEGMENT DW 200 DUP(?) STACKSG ENDS CODESG SEGMENT ASSUME CS:CODESG,DS:DATASG,SS:STACKSG START: MOV AX,DATASG MOV DS,AX MOV AX,STACKSG MOV SS,AX MOV SP,200 ;=============输出菜单1================== MAIN_MENU1: 数组和链表 MOV AX,0003H ;清屏 INT 10H SHOW MENU1 ;输出菜单1 MOV AH,01H INT 21H XOR AH,AH CMP AX,'L' ;JZ _LODEFILE ;暂时不做处理 CMP AX,'C' JZ CALL_INPUT CMP AX,'E' JZ ENDPROC CMP AX,'1' ;JZ _LODEFILE ;暂时不做处理 CMP AX,'2' JZ CALL_INPUT CMP AX,'3' JZ ENDPROC JMP MAIN_MENU1 ;=============输出菜单2================= MAIN_MENU2: MOV AX,0003H ;清屏 INT 10H SHOW MENU2 ;输出菜单2 MOV AH,01H INT 21H XOR AH,AH CMP AX,'1' ;JZ CALL_OUTPUT1 ;学号排序暂时不做处理 CMP AX,'2' JZ CALL_OUTPUT2 ;按总分排序 CMP AX,'3' JZ MAIN_MENU1 JMP MAIN_MENU2 ;输入3位学号、姓名、语文、数学成绩,并计算总成绩,其中输入姓名、成绩以空格结束 CALL_INPUT: MOV AX,0003H ;清屏 INT 10H SHOW INPUT_NUMBER MOV AH,1 INT 21H SUB AL,30H XOR AH,AH MOV NUMBER,AX CRLF SHOW INPUT_INFO CALL INPUT JMP MAIN_MENU2 ;按学号由小到大进行输出(先进行按学号由小到大排序) CALL_OUTPUT1: ;按总分由大到小进行输出(先进行按总分由大到小排序) CALL_OUTPUT2: MOV AX,0003H ;清屏 INT 10H SHOW OUTPUT_INFO CALL SORT_SCORE CALL OUTPUT SHOW PRESS_KEY MOV AH,01H INT 21H JMP MAIN_MENU2 ENDPROC: MOV AH,4CH INT 21H ;===============输入学生成绩信息子程序=============== INPUT PROC NEAR PUSH AX PUSH BX PUSH CX PUSH DX PUSH DI MOV BX,OFFSET S_ARRAY MOV CX,COUNT LOOP11: PUSH CX MOV DI,00H MOV CX,03H LOOP12: MOV AH,01H INT 21H MOV [BX].ID[DI],AL ;输入学号 INC DI LOOP LOOP12 BLANK 03H MOV DI,00H MOV CX,06H LOOP13: MOV AH,01H INT 21H CMP AL,' ' JZ NEXT MOV [BX].NAMES[DI],AL ;输入姓名 INC DI LOOP LOOP13 NEXT: BLANK 04H CALL INPUTGRADE MOV [BX].CSCORE,DH BLANK 08H CALL INPUTGRADE MOV [BX].MSCORE,DH ADD DH,[BX].CSCORE ;计算总分 MOV [BX].SUM,DH CRLF ADD BX,TYPE S_ARRAY ;地址增加一个结构的大小 POP CX LOOP LOOP11 POP DI POP DX POP CX POP BX POP AX RET INPUT ENDP ;================按总分排序子程序2,由高到低=================== SORT_SCORE PROC NEAR PUSH AX PUSH BX PUSH CX PUSH SI PUSH DI MOV CX,COUNT LOOP21: PUSH CX MOV CX,COUNT MOV BX,OFFSET S_ARRAY MOV AL,0 LOOP22: CMP [BX].LINK,0 JNZ L21 CMP AL,[BX].SUM JAE L21 MOV AL,[BX].SUM MOV DI,BX ;将总分最高的学生地址保存在 DI 中 L21: ADD BX,TYPE S_ARRAY LOOP LOOP22 POP CX CMP CX,LENGTH S_ARRAY JNE L22 MOV DX,DI ;总分较高的学生的地址保存在 DX 中 JMP L23 L22: MOV [SI].LINK,DI L23: MOV SI,DI MOV [SI].LINK,1 ;表明该节点已经比较过 LOOP LOOP21 POP DI POP SI POP CX POP BX POP AX RET SORT_SCORE ENDP ;===============输出子程序,按单链表方式================= OUTPUT PROC NEAR ;DX中存放头指针,将头指针赋值BX PUSH AX PUSH BX PUSH CX PUSH SI MOV BX,DX MOV CX,COUNT LOOP31: PUSH CX MOV SI,0 MOV CX,3 LOOP32: MOV DL,[BX].ID[SI] ;输出学号 MOV AH,02H INT 21H INC SI LOOP LOOP32 BLANK 03H MOV SI,0 NEXT1: MOV AH,02H MOV DL,[BX].NAMES[SI] ;输出姓名 CMP DL,'$' JZ NEXT2 INT 21H INC SI JMP NEXT1 NEXT2: BLANK 04H MOV DH,[BX].CSCORE CALL PRINTGRADE ;输出语文成绩 BLANK 08H MOV DH,[BX].MSCORE CALL PRINTGRADE ;输出数学成绩 BLANK 05H MOV DH,[BX].SUM CALL PRINTGRADE ;输出总成绩 CRLF CMP [BX].LINK,1 ;指针为1表明为链表最后一个节点,跳出循环 MOV AX,[BX].LINK MOV BX,AX POP CX LOOPNZ LOOP31 POP SI POP CX POP BX POP AX RET OUTPUT ENDP ;===================输出空格子程序=================== BLANK_PROC PROC NEAR LP1: MOV DL,20H MOV AH,02H INT 21H LOOP LP1 RET BLANK_PROC ENDP ;=============输入成绩,将十进制转换为二进制========= INPUTGRADE PROC NEAR PUSH CX PUSH BX MOV CX,4 MOV DH,0 LOOP41: MOV AH,01H INT 21H CMP AL,' ' JE LP41 SUB AL,30H MOV BH,AL MOV BL,10 MOV AL,DH MUL BL ADD AL,BH MOV DH,AL LOOP LOOP41 LP41: POP BX POP CX RET INPUTGRADE ENDP ;==========输出成绩,将二进制转化为十进制=========== PRINTGRADE PROC NEAR PUSH BX MOV AH,0 MOV AL,DH MOV BL,100 DIV BL MOV DH,AH MOV DL,AL CMP DL,0 JE L42 AND DL,0FH OR DL,30H ;输出百位 MOV AH,02H INT 21H L42: MOV AL,DH MOV AH,0 MOV BL,10 DIV BL MOV DH,AH MOV DL,AL AND DL,0FH OR DL,30H ;输出十位 MOV AH,02H INT 21H MOV DL,DH ;输出个位 AND DL,0FH OR DL,30H MOV AH,2 INT 21H POP BX RET PRINTGRADE ENDP CODESG ENDS END START 推荐书籍:王爽 《汇编语言》 | |||||||||||
教 师 评 价 | 评定项目 | A | B | C | D | 评定项目 | A | B | C | D | |
算法正确 | 操作熟练 | ||||||||||
程序结构合理 | 实验结果正确 | ||||||||||
语法、语义正确 | 文字流畅、报告规范 | ||||||||||
其他: 评价教师签名: 2013年11月 25 日 | |||||||||||
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论