DATA_SEG SEGMENT DATA
; 定义分数表,以字为单位
SCORE_TABLE DW 65, 75, 80, 95, 70, 88, 92, 78, 63, 85
; 其他可能的分数...
TOTAL_STUDENTS DW 10 ; 学生总数
DATA_SEG ENDS
CODE_SEG SEGMENT CODE
ASSUME CS:CODE_SEG, DS:DATA_SEG
START:
MOV AX, DATA_SEG ; 初始化数据段寄存器
MOV DS, AX
; 调用 CNTMARKS 子程序统计各分数段人数
; 60-69
MOV SI, OFFSET SCORE_TABLE ; 分数表的首地址
MOV CX, TOTAL_STUDENTS ; 学生总数
MOV AL, 60 ; 最小值
MOV AH, 69 ; 最大值
CALL CNTMARKS ; 调用子程序
MOV DL, 0 ; 重置 DL 寄存器
; 此时 DL 包含了分数段 60-69 的人数
; 70-79
MOV SI, OFFSET SCORE_TABLE ; 分数表的首地址
MOV CX, TOTAL_STUDENTS ; 学生总数
MOV AL, 70 ; 最小值
MOV AH, 79 ; 最大值
CALL CNTMARKS ; 调用子程序
MOV DL, 0 ; 重置 DL 寄存器
; 此时 DL 包含了分数段 70-79 的人数
; 80-89
MOV SI, OFFSET SCORE_TABLE ; 分数表的首地址
MOV CX, TOTAL_STUDENTS ; 学生总数
MOV AL, 80 ; 最小值
MOV AH, 89 ; 最大值
CALL CNTMARKS ; 调用子程序
MOV DL, 0 ; 重置 DL 寄存器
; 此时 DL 包含了分数段 80-89 的人数
; 90-100
MOV SI, OFFSET SCORE_TABLE ; 分数表的首地址
MOV CX, TOTAL_STUDENTS ; 学生总数
MOV AL, 90 ; 最小值
MOV AH, 100 ; 最大值
CALL CNTMARKS ; 调用子程序
MOV DL, 0 ; 重置 DL 寄存器
; 此时 DL 包含了分数段 90-100 的人数
; 可以在这里输出结果或者进行其他操作
; 程序结束
MOV AH, 4CH
INT 21H
CODE_SEG ENDS
END START
; CNTMARKS 子程序
; 功能:统计(AL,AH)分数段的人数。
; 入口参数:DS:SI 为需统计的分数表首地址,CX 中为总人数,AL 为要统计的分数段最小值,AH 为要统计的分数段最大值。
; 出口参数:DL,指定分数段(AL,AH)的人数
CNTMARKS PROC
MOV CX, 0 ; 初始化计数器为0
MOV DI, 0 ; 初始化索引为0
; 检查 SI 是否指向分数表的末尾
NEXT_SCORE:
CMP DI, CX ; 比较索引与总人数
JAE END_COUNT ; 如果所有分数都已处理完,则跳到计数结束
MOV AX, [SI] ; 从分数表加载下一个分数到 AX
CMP AL, AH ; 比较最小值和最大值
JA INVALID_RANGE ; 如果最小值大于最大值,则跳到无效范围处理
CMP AX, AL ; 比较分数与最小值
JB NOT_IN_RANGE ; 如果分数低于最小值,则跳到不在范围内处理
CMP AX, AH ; 比较分数与最大值
JA NOT_IN_RANGE ; 如果分数高于最大值,则跳到不在范围内处理
INC CX ; 如果分数在指定范围内,增加计数器
NOT_IN_RANGE:
ADD SI, 2 ; 移到表中的下一个分数
INC DI ; 增加索引
JMP NEXT_SCORE ; 继续下一次迭代
INVALID_RANGE:
; 处理最小值大于最大值的情况
; 在这里你可以设置DL为特定值或者根据需要处理错误
MOV DL, 0FFH ; 设置DL为一个特殊值,表示错误
JMP END_COUNT ; 跳到计数结束
END_COUNT:
MOV DL, CX ; 将计数值移动到DL寄存器,用于输出
RET
CNTMARKS ENDP