汇编结构体实现简单的学生成绩管理并排序

【获取源码】:https://github.com/chesterblue/asm_manage_grade  欢迎大家star

使用汇编实现简单的学生成绩管理并排序,其中排序使用的是冒泡排序

本程序是使用结构体实现的,运行环境为Masm for Windows 集成实验环境 2015

以下为核心代码

结构体的定义,名字占20字节,成绩为字类型数据,主要是为了后面输入输出中的计算方便:

STUDENT STRUC			;结构定义
		NAMES DB 20 DUP (?)
		SCORE dw ?
STUDENT ENDS

 结构体数组的定义:

CNT = 10
CLASS STUDENT CNT DUP(<>)

 以下代码中出现的变量:

    CN DW 10		;乘数  
    COUNT DW ?		;记录人数
    REAL_COUNT DW 0	;此变量值为提示正在输入第几个学生的信息
    CHN1 DW 2		;除数
    CHN2 DW 10		;除数
    OPT DB ?		;菜单选项的保存
    INSIDE DW ?		;排序时使用到的内循环
    OUTSIDE DW ?	;外循环
    FIXNUM DW 22
    NOWS DW 0		;记录当前输入信息的地址
    RANK DW 0		;记录当前排名
    TEMP1 DB 20 DUP(?)
    TEMP2 DB 20 DUP(?)
    ERROR DB 'INPUT ERROR!',13,10,'$'
    NAME_TIP DB 'Name:$'
    SCORE_TIP DB 'Score:$'
    INPUT_TIP1 DB 'NO.$'
    INPUT_TIP2 DB ' STUDENT',13,10,'$'
    CLR DB 13,10,'$'
    INPUT_TIP3 DB 'Click any key to continue,ESC to exit',13,10,'$'
    OUTPUT_TIP1 DB 'Name',15 DUP(' '),'$'
    OUTPUT_TIP2 DB 'Score',5 DUP(' '),'$'
    OUTPUT_TIP3 DB 'Rank','$'
    BLANK_ONE DB '          $'
    ERROR_MENU_TIP DB 'Please input again!',13,10,'$'

 两个宏指令分别实现字符串输出的功能,以及不定位数数字的输出

;----宏指令字符串的输出----
PRINTS MACRO STR
	MOV AH,9
	LEA DX,STR
	INT 21H
	ENDM
;------宏指令输出不定位数的数字-----
PRINTN MACRO NUM
	LOCAL LP1,LP2
	 XOR CX,CX
	 MOV AX,NUM
	 CWD   
LP1:
	DIV CHN2
	PUSH DX
	INC CX
	CMP AX,0
	CWD       ;重点!!!!!!!
	JNZ LP1
LP2:
	POP DX
	ADD DL,30H
	MOV AH,2
	INT 21H
	LOOP LP2	
ENDM

 此次实验中输入成绩与存储成绩是最为关键的地方,因为成绩可以是一位数字,也可以是两位数字,更可以是三位数字,怎样保存一个学生的成绩,怎样判断一个学生的成绩输入结束,就是本次实验的难点。以下代码就是我解决这些问题的具体方法。

NEXT1:
	MOV CLASS[BX].NAMES[19],'$'
	PUSH BX			;保护BX
LOOP_TIP:	
	PRINTS SCORE_TIP
	XOR DX,DX
	XOR BX,BX
LOOP2:
    MOV AH,1
    INT 21H
    CMP AL,0DH		;判断是否为回车退出
    JZ STORE
    SUB AL,30H
    
    JL    ERROR1         ; <0 报错 重新输入
    CMP   AL, 9
    JG    ERROR1         ; >9 报错 重新输入
    
    CBW
    XCHG AX,BX
    MUL CN
    ADD BX,AX
    JMP LOOP2    
ERROR1:
    PRINTS ERROR
    JMP LOOP_TIP
STORE:
	MOV DX,BX
	CMP DX,100			;判断输入的成绩是否有效
	JA ERROR1
	POP BX
	MOV CLASS[BX].SCORE,DX
    INC CX				;记录学生人数
    PRINTS CLR
    PRINTS INPUT_TIP3	;输出提示
    MOV COUNT,CX
    ADD BX,FIXNUM
    MOV NOWS,BX	;存储下一个学生信息的地址
    MOV AH,1
    INT 21H
    CMP AL,1BH			;判断是否为ESC
    JNZ OP1_NEW

此次实验的另一个难点就是排序,我用的是冒泡排序的方法,其中判断大小后怎样调换两个学生的信息是关键。

OP2_NEW:
	XOR BX,BX
	MOV CX,REAL_COUNT
	DEC CX
 	MOV OUTSIDE,CX	;使学生人数减一后给OUTSIDE
OUT_LOOP:
	MOV CX,OUTSIDE
	MOV INSIDE,CX
	MOV BX,0		;初始化地址
IN_LOOP:
	MOV CX,CLASS[BX].SCORE
	ADD BX,FIXNUM
	CMP CX,CLASS[BX].SCORE
	JL EXCHANGE
	;以下为循环条件
	DEC INSIDE
	CMP INSIDE,0
	JG IN_LOOP
	DEC OUTSIDE
	CMP OUTSIDE,0
	JG OUT_LOOP
	JMP NEXT
EXCHANGE:
;-----成绩位置交换------
	MOV DX,CLASS[BX].SCORE	;把小的数给DX
	SUB BX,FIXNUM
	MOV CLASS[BX].SCORE,DX	;把DX给原本存大数的位置
	ADD BX,FIXNUM
	MOV CLASS[BX].SCORE,CX	;把CX给原本存小数的位置
;-----姓名位置交换-------
	LEA SI,CLASS[BX].NAMES
	LEA DI,TEMP1			;串操作把小数的名字给临时变量一
	MOV CX,20
	REP MOVSB
	
	SUB BX,FIXNUM
	LEA SI,CLASS[BX].NAMES	;串操作把大数的名字给临时变量二
	LEA DI,TEMP2
	MOV CX,20
	REP MOVSB
	
	LEA SI,TEMP1
	LEA DI,CLASS[BX].NAMES	
	MOV CX,20
	REP MOVSB
	
	ADD BX,FIXNUM
	LEA SI,TEMP2
	LEA DI,CLASS[BX].NAMES
	MOV CX,20
	REP MOVSB
	;以下为循环条件
	DEC INSIDE
	CMP INSIDE,0
	JG IN_LOOP	
	DEC OUTSIDE
	CMP OUTSIDE,0
	JG OUT_LOOP

最后的成绩按名次输出就比较简单了,能做到姓名、成绩、名次的清晰划分即可,所以就不在此赘述了。 

以下为程序运行图: 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值