21,459
社区成员
发帖
与我相关
我的任务
分享
;本程序是从键盘输入学生姓名和成绩,按成绩升序排序,并显示结果
DATAS SEGMENT
INFOR0 DB 0AH,0DH,'SORT=$'
INFOR1 DB 0AH,0DH,'INPUT NAME:$'
INFOR2 DB 0AH,0DH,'SCORE:$'
N EQU 8 ;姓名长度
M EQU 4 ;成绩长度(3位+回车符)
P EQU 3 ;输入的人数
Q EQU 3 ;成绩位数
BUFF1 DB N,?,N DUP(0),'$'
BUFF2 DB M,?,M DUP(0),'$'
SNAME DB P DUP(N+1 DUP(0)) ;保存姓名
SCORE1 DW P DUP(M+1 DUP(0)) ;保存成绩
SCORE2 DW P DUP(M+1 DUP(0))
CIXU DB P DUP(0) ;输入次序
X DW ?
SIGN1 DW 0
SIGN2 DW 0
CONT DB '1'
DATAS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS
MAIN PROC FAR
START:
MOV AX,DATAS
MOV DS,AX
MOV ES,AX
MOV BX,0
MOV CX,0
CALL INPUT
CALL SORT
CALL PRINT
MOV AH,4CH
INT 21H
MOV AH,4CH
INT 21H
MAIN ENDP
;---------------------------------------------------------------------
;输入姓名成绩
;---------------------------------------------------------------------
INPUT PROC
INC BX
CMP BX,P ;到达输入的最大人数了吗
JA EXIT ;超过了,退出
LEA DX,INFOR1 ;显示提示信息
MOV AH,9
INT 21H
LEA DX,BUFF1 ;接收BUFF1
MOV AH,10
INT 21H
MOV AL,BUFF1+1 ;实际输入个数
ADD AL,2 ;加2,包含buff1的0,1号单元
MOV AH,0
MOV SI,AX
MOV BUFF1[SI],0 ;回车0d换为0,便于输出显示
LEA DX,INFOR2 ;显示提示信息
MOV AH,9
INT 21H
;----------------
;这里得进输入串的功能
LEA DX,BUFF2 ;接收BUFF2
MOV AH,10
INT 21H
;--------------------
MOV AL,BUFF2+1 ;实际输入的字符数
ADD AL,2 ;追回2个字节
MOV AH,0
MOV SI,AX
MOV BUFF2[SI],0 ;换为0
MOV CIXU[BX-1],BL ;BX初值为3
CMP BX,1
JZ LET1 ;第一次不需要设置了,跳出
ADD SIGN1,N +1 ;姓名长度
ADD SIGN2,Q ;成绩位数
LET1:
CALL COPY
JMP INPUT
EXIT:
RET
INPUT ENDP
;---------------------------------------------------------------------
;数据转存
;---------------------------------------------------------------------
COPY PROC
MOV CX,N+1 ;姓名长度+1(连最后的'$'也包括进来了)
LEA SI,BUFF1+2 ;
LEA DI,SNAME ;目标缓冲区
ADD DI,SIGN1 ;调整接收位置
CLD
REP MOVSB ;复制姓名
MOV CX,N
MOV AX,'$'
LEA DI,BUFF1+2
REP STOSB ;将串BUFF1+2置'$'
;有了上面两处的置'$',所以用dos 中断9号功能显示是可行的。
MOV CX,M+1
LEA SI,BUFF2+2
LEA DI,SCORE1
ADD DI,SIGN2
CLD
REP MOVSB ;复制成绩
LEA SI,BUFF2+2
MOV DI,SIGN2
CALL CHANGE ;将成绩转换成二进制
RET
COPY ENDP
;---------------------------------------------------------------------
;十进制数ASCII→二进制
;---------------------------------------------------------------------
CHANGE PROC
MOV X,0
MOV CX,[SI-1] ;实际字符数
AND CX,000FH ;实际字符数
REPT2:
MOV AL,[SI]
CMP AL,30H
JL EXIT1
CMP AL,39H
JG EXIT1
AND AX,000FH
XCHG AX,X ;X保存上次的积
MOV DX,10
MUL DX
ADD X,AX ;X保存上次的积
INC SI
LOOP REPT2
MOV AX,X
MOV SCORE2[DI],AX
MOV X,0
ADD SIGN2,2
EXIT1: RET
CHANGE ENDP
;---------------------------------------------------------------------
;排序
;---------------------------------------------------------------------
SORT PROC
MOV CX,P
DEC CX ;最大人数-1
LOOP1:
PUSH CX
MOV BX,0
MOV SI,0
LOOP2:
MOV AX,SCORE2[BX]
CMP AX,SCORE2[BX+M+1]
JGE NEXT
;交换成绩
XCHG AX,SCORE2[BX+M+1]
MOV SCORE2[BX],AX
;交换名次
MOV AL,CIXU[SI]
XCHG AL,CIXU[SI+1]
MOV CIXU[SI],AL
NEXT:
ADD BX,M+1 ;指向下一成绩
INC SI ;指向下一名次
LOOP LOOP2
POP CX
LOOP LOOP1 ;--CX , 如果cx!=0 再循环
;(算法不科学,如果输入就是排好序的,
;那不是也要循环cx次?)
RET
SORT ENDP
;---------------------------------------------------------------------
;输出
;---------------------------------------------------------------------
PRINT PROC
LEA DX,INFOR0
MOV AH,9
INT 21H
MOV CX,P
MOV BX,0
MOV AX,0
MOV DI,0
REPT3:
;回车换行
MOV DL,0AH
MOV AH,2
INT 21H
MOV DL,0DH
INT 21H
;显示count
MOV DL,CONT ;(如果人数多于9个什么显示什么?)
MOV AH,2
INT 21H
INC CONT ;(如果人数多于9个什么显示什么?)
;回车换行
MOV DL,0AH
MOV AH,2
INT 21H
MOV DL,0DH
INT 21H
MOV AX,0
MOV AL,CIXU[DI]
DEC AL
MOV BL,9 ;姓名域尺寸
MUL BL
LEA DX,SNAME
ADD DX,AX
MOV AH,9
INT 21H
;换行回车(应该0Dh在前)
MOV DL,0AH
MOV AH,2
INT 21H
MOV DL,0DH
MOV AH,2
INT 21H
MOV AX,0
MOV BX,0
MOV AL,CIXU[DI]
DEC AL
MOV BL,5 ;成绩域尺寸
MUL BL
LEA DX,SCORE1
ADD DX,AX
MOV AH,9
INT 21H
INC DI
LOOP REPT3
RET
PRINT ENDP
CODES ENDS
END MAIN ;START