汇编语言综合大实验,实现学生成绩
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
主要完成5个功能
- 功能一:进入时,设计密码输入验证功能;
- 功能二:键盘输入全班同学(35人)的总成绩;
- 功能三:对全班同学的成绩进行从高到低的排名并在显示器上 显示结果;
- 功能四:统计出不及格的人数并在显示器上输出。
- 功能五:统计并求出全班的平均成绩,在显示器上输出平均成绩。
一、数据段代码块
DATAS SEGMENT
HINT_1 DB "please input password:",0AH,0DH,'$'
HINT_2 DB "password wrong !",0AH,0DH,'$'
HINT_3 DB "three times !",0AH,0DH,'$'
HINT_4 DB "password success !",0AH,0DH,'$'
HINT_5 DB "error,please input a number !",0AH,0DH,'$'
HINT_6 DB "please input the grade:",0AH,0DH,'$'
HINT_7 DB "GRADE SUCCESS !",0AH,0DH,'$'
HINT_8 DB "number of failed:",0AH,0DH,'$'
HINT_9 DB "the average grade is:",0AH,0DH,'$'
HINT_10 DB "PLEASE CHOOSE:",0AH,0DH,"3.SORT",0AH,0DH,"4.FAILED",0AH,0DH,"5.AVERAGE",0AH,0DH,"6.EXIT",0AH,0DH,'$'
COUNT_1 DB 3;最大输入次数
COUNT_2 DW 6;密码的个数
COUNT_3 DW 35;班级同学人数
COUNT_4 DW 68;用于记录人数在内存中最后的下标,即COUNT_3*2-2
COUNT_5 DW 0;用于记录不及格的人数
COUNT_6 DW 3;保留3位小数
COUNT_7 DW ?;记录用户输入的密码个数
PASSWORD DB "111111"
STRING DB 20 DUP(0)
CRLF DB 0AH,0DH,'$'
N DW ?
NUM DW 0;存储当前字符
FLAG_1 DB 0;0代表不是数字,1代表是数字
GRADE DW 35 DUP(0);存储35个学生成绩
;GRADE DW 2,4,3,7
TEN DW 10
SIXTY DW 60;及格分
INDEX DW 0
AVERAGE DW 0
CHOOSE DB ?;用户输入的选择
DATAS ENDS
STACKS SEGMENT PARA STACK
DW 20H DUP(0)
;此处输入堆栈段代码
STACKS ENDS
二、设计密码输入验证功能
设置默认密码为“111111”。每输入一个密码将其以“*”显示在显示屏上,输入结束后将其与默认密码进行比较,若不相同,则提示重新输入,当输入密码错误3次,则结束程序,若密码输入正确,则进入功能2。具体代码如下:
;密码输入与检测
LOP1 PROC
CMP COUNT_1,0;如果输入了三次错误密码,则结束程序
JZ END1
DEC COUNT_1
MOV SI,0
MOV BX,COUNT_2
MOV COUNT_7,0
INITIAL:;初始化,将数组元素置为0
MOV STRING[SI],0
INC SI
DEC BX
CMP BX,0
JNZ INITIAL
MOV SI,0
MOV DX,OFFSET HINT_1
MOV AH,09H
INT 21H
;输入密码
INPUTPASSWORD:
MOV AL,0
MOV AH,08H
INT 21H
CMP AL,0DH;判断是否为回车,是的话说明输入结束
JZ CHECK
MOV STRING[SI],AL
INC SI
INC COUNT_7
MOV DL,'*'
MOV AH,02H
INT 21H
JMP INPUTPASSWORD
;检测密码输入是否正确
CHECK:
LEA DX,CRLF;输出换行
MOV AH,09H
INT 21H
MOV CX,COUNT_7
CMP COUNT_2,CX
JNZ CONTINUE;密码个数不对,密码错误
MOV DI,OFFSET STRING
MOV SI,OFFSET PASSWORD
CLD
REPZ CMPSB
JZ SUCCESS;密码正确
CONTINUE:
MOV DX,OFFSET HINT_2
MOV AH,09H
INT 21H
JMP LOP1
;密码错误三次,结束程序
END1:
MOV DX,OFFSET HINT_3
MOV AH,09H
INT 21H
MOV AH,4CH
INT 21H
SUCCESS:
LEA DX,HINT_4
MOV AH,09H
INT 21H
RET
LOP1 ENDP
三、键盘输入全班同学(35人)的总成绩
每输入一个数字就将其与之前获得的数字乘10再相加,当遇到空格时,表示一个数据输入成功,此时将其存入到成绩数组中,当输入的字符不是数字时,提示用户输入非法并让用户重新输入该数据。
;键盘输入全班同学总成绩
LOP2 PROC
MOV CX,0
MOV SI,0
LEA DX,HINT_6
MOV AH,09H
INT 21H
INPUT:
;CMP CX,0
;JZ END2;当输入完35个数字后结束输入
MOV AH,01H
INT 21H
CMP AL,0DH;遇到回车说明一个数据输入完成
JZ SAVENUM
;JZ END2
CMP AL,' ';遇到空格说明一个数据输入完成
JZ SAVENUM;
MOV DL,AL
MOV DH,0
PUSH DI
PUSH DX
CALL ISDIGITAL
POP DX
POP DI
CMP FLAG_1,0;如果不是数字,则要求重新输入
JZ INPUT
;MOV NUM,0
MOV N,DX
SUB N,30H
MOV AX,NUM
MUL TEN
ADD AX,N
MOV NUM,AX
JMP INPUT
;存储输入的成绩
SAVENUM:
INC CX
MOV BX,NUM
MOV GRADE[SI],BX
MOV NUM,0
ADD SI,2
CMP AL,0DH;如果输入的是回车,则结束输入
JZ END2
JMP INPUT
;输入完成
END2:
MOV COUNT_3,CX
LEA DX,HINT_7
MOV AH,09H
INT 21H
RET
LOP2 ENDP
;判断输入的是否为数字字符
ISDIGITAL PROC
MOV BP,SP
MOV DI,[BP+2]
ISBIGGER:;如果0更大的话就跳到非数字
CMP DI,'0'
JB NONDIGITAL
ISSMALL:;如果9更大的话就跳到数字
CMP DI,'9'
JBE DIGITAL
JMP NONDIGITAL
NONDIGITAL:
MOV FLAG_1,0
CALL OUTPUTCRLF
LEA DX,HINT_5
MOV NUM,0;将缓存的数据清零
MOV AH,09H
INT 21H
RET
DIGITAL:
MOV FLAG_1,1
RET
ISDIGITAL ENDP
四、冒泡排序,输出成绩
用冒泡排序对所有成绩进行从大到小的排序,然后调用将二进制转换为十进制的子程序将每个数据转换为其对应的ASCII码显示到屏幕上。
;从高到低排名
LOP3 PROC
MOV CX,0
FIRST:
MOV DI,0
INC CX
CMP CX,COUNT_3
JZ OUTPUT_3
COMPARE:
MOV BX,GRADE[DI]
CMP BX,GRADE[DI+2]
JB SWAP
RETURN1:
ADD DI,2
CMP COUNT_4,DI
JZ FIRST
JMP COMPARE
SWAP:;交换
MOV AX,GRADE[DI+2]
MOV GRADE[DI],AX
MOV GRADE[DI+2],BX
JMP RETURN1
OUTPUT_3:;比较结束
MOV CX,COUNT_3
MOV SI,0
OUTPUT0:
MOV AX,GRADE[SI]
PUSH AX
CALL OUTPUT
CALL OUTPUTSPACE
ADD SI,2
DEC CX
CMP CX,0
JNZ OUTPUT0
CALL OUTPUTCRLF
RET
LOP3 ENDP
其流程图如下:
五、输出不及格人数
遍历成绩数组,用一个计数器存储不及格人数,初值为0,当该成绩小于60时,计数器加1,遍历结束后,调用将二进制转换为10进制的子程序输出该结果。
;输出不及格的人数
LOP4 PROC
MOV COUNT_5,0
MOV SI,0
MOV CX,0
COMPARE2:
MOV BX,SIXTY
CMP GRADE[SI],BX
JB ACCOUNT
RETURN2:
ADD SI,2
INC CX
CMP CX,COUNT_3
JNZ COMPARE2
JZ END4
;不及格人数加1
ACCOUNT:
INC COUNT_5
JMP RETURN2
END4:
;输出不及格人数
LEA DX,HINT_8
MOV AH,09H
INT 21H
MOV AX,COUNT_5
PUSH AX
CALL OUTPUT
CALL OUTPUTCRLF
RET
LOP4 ENDP
六、求平均成绩
遍历成绩数组,将每个成绩相加,结果存入AX寄存器中,将AX寄存器中的数值除以总人数,获得商,并将其输出,再将余数乘以10除以总人数,获得第一位小数,以此类推,循环3次后,输出小数部分。
;求平均成绩
LOP5 PROC
MOV SI,0
MOV CX,COUNT_3
DEC CX
MOV BX,GRADE[SI]
ADD AVERAGE,BX
ADDSUM:
ADD SI,2
MOV BX,GRADE[SI]
ADC AVERAGE,BX
LOOP ADDSUM
LEA DX,HINT_9
MOV AH,09H
INT 21H
MOV AX,AVERAGE
CWD
DIV COUNT_3
PUSH DX;保护余数
PUSH AX
CALL OUTPUT
MOV DX,'.'
MOV AH,02H
INT 21H
MOV CX,COUNT_6
POP AX
;小数的处理
DECIMAL:
MUL TEN
CWD
DIV COUNT_3
PUSH DX;保护余数
PUSH AX;输出商
CALL OUTPUT
POP AX;余数继续乘10再除以除数
LOOP DECIMAL
CALL OUTPUTCRLF
RET
LOP5 ENDP
七、二进制转十进制输出
在调用前需要先将想输出的二进制数存入栈中,然后在子程序里令AX等于BP+2的值,令INDEX等于0,当AX不等于0时,将AX除以班级人数,将余数加上30H后入栈,同时INDEX加1,当AX等于0时,输出栈里的数据,最后结束子程序时将一开始进栈的二进制数一起弹出栈。
;二进制转十进制的输出子程序,要将想输出的数据压入栈,改变了AX,DX
OUTPUT PROC
MOV BP,SP
MOV AX,[BP+2]
MOV INDEX,0
OUTPUT2:
CWD
DIV TEN
ADD DX,30H
PUSH DX
INC INDEX
CMP AX,0
JZ OUTPUT3
JMP OUTPUT2
OUTPUT3:
CMP INDEX,0
JZ OUTPUTEND
POP DX
MOV AH,02H
INT 21H
DEC INDEX
JMP OUTPUT3
OUTPUTEND:
RET 2
OUTPUT ENDP
;输出空格
OUTPUTSPACE PROC
MOV DX,20H
MOV AH,02H
INT 21H
RET
OUTPUTSPACE ENDP
;输出换行
OUTPUTCRLF PROC
LEA DX,CRLF
MOV AH,09H
INT 21H
RET
OUTPUTCRLF ENDP
八、主程序
先调用功能1子程序,再调用功能2子程序,然后输出菜单供用户选择,当用户输入3时,调用功能3子程序,输入4时,调用功能4子程序,输入5时,调用功能5子程序,直到输入6时,结束程序。
;主程序
MAIN:
CALL LOP1
CALL LOP2
LEA DX,HINT_10
MOV AH,09H
INT 21H
SETCHOOSE:
MOV AH,01H
INT 21H
MOV CHOOSE,AL
CALL OUTPUTCRLF
CMP CHOOSE,'3'
JZ CALL3
CMP CHOOSE,'4'
JZ CALL4
CMP CHOOSE,'5'
JZ CALL5
CMP CHOOSE,'6'
JZ ENDMAIN
JNZ SETCHOOSE
CALL3:
CALL LOP3
JMP SETCHOOSE
CALL4:
CALL LOP4
JMP SETCHOOSE
CALL5:
CALL LOP5
JMP SETCHOOSE
总结
本次实验主要练习了子程序的使用和各种传参方式,是一个比较考验汇编编程综合能力的实验。