《  汇 编 语 言》课程综合性实验报告
实验题目
显示学生名次表
一、实验目的
    通过显示学生成绩名次表,进行汇编语言程序设计应用的综合性训练。综合运用汇编语言循环程序、子程序、宏指令编程方法,提高汇编语言程序设计能力的应用水平。
二、设备与环境
    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小时内删除。