微机原理实验 统计考试成绩


前言

这是笔者微机原理的结课大作业,看到这里相信应该读者已经掌握了绝大部分课程所需的知识。

一、项目要求

编写以完整程序,要求显示班级号,班级人数,接收年月日信息并送显,键盘输入班级同学的高数成绩,求最高分、最低分、平均分,并全部显示出来。

二、思路介绍

从本程序中有着以下的几个部分,首先是获取从键盘上输入的信息。首先程序采用DOS软中断的09H号命令,获得键盘输入的年月日信息。紧接着程序采用DOS软中断的01H号命令,对逐位数据输入,获取每个同学的成绩。

接下来便是需要处理这些获取的成绩,通过十位×10 +个位的方式,将每次输入的两个单元的信息内容合并成一个单元的数据。其中×10的操作采用向左移动3次加向左移动一次完成,提高程序的执行效率。

紧接着就是获取处理好的这堆内容的各项信息,通过从首地址进行遍历,找到这堆成绩中的最高分,最低分和总分,并保存下来,通过用总分整除人数,即可获得班级同学的平均分。

最后,在屏幕上输出提示信息,并将各类处理好的结果输出上去,即可完成本次项目的要求。

三、各类子程序介绍

程序初始化 (START)
设置数据段寄存器,显示班级信息,然后请求输入当前日期和学生成绩。

输入成绩 (INPUT_GRADE PROC)
通过循环接收用户输入的成绩,并将其存储在GRADE数组中。每次读取两个字符(假设成绩为两位数),并在读取每个成绩后跳过一个空格。

输出成绩 (OUTPUT_GRADE PROC)
将成绩输出到屏幕上,这通常用于调试。

转换成绩 (CONVERT PROC)
将输入的ASCII码表示的数字转换为实际的数值,并计算每个学生的成绩,存储在GRADE数组中。

查找成绩 (FIND_GRADE PROC)
计算最高分、最低分和平均分。遍历GRADE数组,同时累加总分,然后计算平均分。

显示结果 (SHOW PROC)
将数值转换为ASCII码并显示到屏幕上。该子程序使用了除法和栈来反转数字,因为它从最低位开始打印,直到所有数字都被处理。

四、程序流程图

五、程序代码及注释

DATAS SEGMENT
	NUM EQU 20									;班级人数
	GRADE DB 100 dup(?)  						;成绩存放位置
	CRLF DB 0AH,0DH,'$'							;换行,清晰程序
	MAX DB 0  									;存放最大值
   	MIN DB 0  									;存放最小值
   	TOTAL DW 0  								;存放全体数的和
   	AVG DB 0									;存放平均数
   	MAX_MSG DB 'The highest score is: ','$'		;最高分提示信息
   	MIN_MSG DB 'The lowest score is: ','$'		;最低分提示信息
   	AVG_MSG DB 'The average score is: ','$'		;最低分提示信息
   	DATE_MSG DB 'Today is: ','$'				;日期提示信息
	BUFFER1 DB 101,?,101 DUP (?)				    					;第一个101表示最大长度为101个字符,?占用的那个字节在调用结束后会被放入实际输入的字符个数
	CLASS_MEG DB 'The class is XXX',0AH,0DH,'$'						;班级号信息
    NUM_MEG DB 'The class size is 20',0AH,0DH,'$'						;班级人数信息
    ASK_MEG1 DB 'Please input the current date,for example: 2023.12.04',0AH,0DH,'$'		;输入时间提示信息
    ASK_MEG2 DB 'Please input grades,separated by space: ',0AH,0DH,'$'					;输入成绩提示信息

DATAS ENDS

STACKS SEGMENT
	DW 256 DUP (?)								;涉及到进入子程序的断点保护,需要入栈出栈
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
	;初始化
    MOV AX,DATAS
    MOV DS,AX 
	
	LEA DX,CLASS_MEG   			;提示信息
	MOV AH,09H
	INT 21H
	LEA DX,NUM_MEG   			;提示信息
	MOV AH,09H
	INT 21H
	LEA DX,ASK_MEG1   			;日期提示信息
	MOV AH,09H
	INT 21H
	;输入日期到缓冲区
    LEA DX,BUFFER1
    MOV AH,0AH
    INT 21H
    MOV AL, BUFFER1+1                     ;对字符串进行处理,该位置为字符串长度
    ADD AL, 2							  ;长度占一个字节,'$'在字符串最末尾,因此加2
    MOV AH, 0
    MOV SI, AX
    MOV BUFFER1[SI], '$'				  ;对字符串最末尾补上'$'
   
    LEA DX,ASK_MEG2   			;成绩提示信息
	MOV AH,09H
	INT 21H
	
	CALL INPUT_GRADE  			;输入成绩 
	;CALL OUTPUT_GRADE   		;输出成绩(检查调试)
	CALL CONVERT		    	;转化成BCD码
	CALL FIND_GRADE				;查找最大值,最小值和平均数
	
	;显示日期
	LEA DX,DATE_MSG
    MOV AH,09H
    INT 21H
	LEA DX,BUFFER1+2
    MOV AH,09H
    INT 21H
    LEA DX,CRLF   				;换行
	MOV AH,09H
	INT 21H
	;显示最高分结果
	LEA DX,MAX_MSG
	MOV AH,09H
	INT 21H
	MOV AL,MAX
	CALL SHOW
	;显示最低分结果
	LEA DX,MIN_MSG
	MOV AH,09H
	INT 21H
	MOV AL,MIN
	CALL SHOW				
	;显示平均分结果
	LEA DX,AVG_MSG
	MOV AH,09H
	INT 21H
	MOV AL,AVG
	CALL SHOW	
	
	;结束程序	
	MOV AH,4CH
	INT 21H

;输入成绩子程序
INPUT_GRADE PROC
	MOV CX,NUM
	LEA SI,GRADE
	
INPUT:
	MOV AH,01H
	INT 21H
	MOV [SI],AL
	
	MOV AH,01H
	INT 21H
	MOV [SI+1],AL
	
	MOV AH,01H				;吃掉空格
	INT 21H
	ADD SI,2				;将指针对准下一个单元
	LOOP INPUT
	RET
INPUT_GRADE ENDP

;输出成绩子程序
OUTPUT_GRADE PROC
	MOV GRADE[SI],'$'		;给最末尾加上'$'用以方便输出检查
	LEA SI,GRADE			;指针移回首地址
	MOV AH,09H
	MOV DX,SI
	INT 21H
	MOV AH,09H      		;换行
	LEA DX,CRLF
	INT 21H
	RET
OUTPUT_GRADE ENDP
	
;转换子程序
CONVERT PROC
	LEA SI,GRADE
	XOR CX,CX
	MOV CX,2*NUM			;两个单元内容合成一个
BEGIN:
	MOV AL,[SI]
	SUB AL,30H   			;ASCII转化为BCD码
	MOV [SI],AL
	INC SI
	LOOP BEGIN

	lea SI,GRADE 
	lea DI,GRADE
	MOV CX,NUM
C1:
	MOV AL,[SI]				
	MOV BL,AL
	SHL BL,1
	SHL AL,1
	SHL AL,1
	SHL AL,1
	ADD AL,BL				;乘以十相当于左移三位加左移一位
	ADD AL,[SI+1]			;十位乘以十加上个位
	MOV [DI],AL				
	ADD SI,2
	INC DI
	LOOP C1
	RET 
CONVERT ENDP

;查找子程序
FIND_GRADE PROC
 	LEA DI,GRADE
 	MOV AH,0H
    MOV AL,[DI]
    ADD TOTAL,AX
    MOV MIN,AL
    MOV MAX,AL
    MOV CX,NUM-1			;设定循环次数
AGAIN:
	INC DI  
	MOV AL,[DI]
	ADD TOTAL,AX         	;总和加上当前AX中的值
	CMP AL,MAX
	JBE L1        			;如果AX<=MAX,则不是最大数,不需要更改MAX的值
	MOV MAX,AL	         	
L1:
	CMP AL,MIN
	JAE L2          		;如果AX>=MIN,则不是最小数,不需要更改MIN的值
	MOV MIN,AL	       
L2:	
	LOOP AGAIN	        	;CX大于0就继续循环
	MOV AX,TOTAL
	MOV BL,NUM
	DIV BL
	MOV AVG,AL				;总分除以人数得到平均分
	RET
FIND_GRADE ENDP

;显示结果子程序
SHOW PROC
	MOV AH,0
	MOV CL,10				;cl是每次 除以 10
    MOV CH,0				;计算除了多少次,也就是有几位
    
L0:
	DIV CL					;ax 除以 cl
	PUSH AX					;此时的商存储在AL中,
							;余数存储在AH中,此时 ax = ah
	ADD CH,1
	MOV AH,0
	CMP AX,0				;如果 ax 是 0,说明除干净了
	JNE L0
	
MY_LOOP: 
	CMP CH,0				;此时CH的值就是位数,每次出栈,然后 ch 减一即可 
	JE OVER
	POP DX					;把栈顶元素存储到 dx 中
	MOV DL,DH				;然后将 dl 的值等于 dh
	ADD DL,48
	MOV AH,02H
	INT 21H
	
	DEC CH
	JMP MY_LOOP
OVER:	
	LEA DX,CRLF
	MOV AH,09H
	INT 21H
	RET
SHOW ENDP
	
 
CODES ENDS
	END START

六、实验结果

七、注意事项

因为题目要求接收年月日笔者默认是手动输入然后再显示出来,就省去了很多的工作量。如果是需要自动获取计算机的年月日,那么需要调用其他的接口进行操作,由于精力原因笔者没有这么做。

如果有需要的话只需要更改一下子程序即可,预祝读者学习顺利。

  • 16
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值