www.pudn.com > cxc002.rar > cxc002.asm
;循环不溢出测试版(成功)+彩色测试版(成功)+随机不重复测试版(成功)+系统时间测试版(成功)
;☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
;☆ 说 明 ☆
;☆ 20以内的加减法 (可供幼儿园小学生练习用) ☆
;☆ 编程设计:程相闯 专业班级:计算机02-1班 指导教师:王卫平 ☆
;☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
;宏定义部分
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DISP MACRO M ;定义宏DISP显示字符串
LEA DX,M
MOV AH,09
INT 21H
ENDM
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DISP1 MACRO N ;定义宏DISP1显示1个字符
MOV DL,N
MOV AH,2
INT 21H
ENDM
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DISPCOLOR MACRO STR,LEN,ROW,COLOR,CHAR ;定义宏DISPCOLOR彩显字符串
MOV BP,SEG STR ;取STR串段地址
MOV ES,BP
MOV BP,OFFSET STR ;取STR串偏移地址
MOV CX,LEN ;字符串长度
MOV DH,ROW ;置行属性
MOV DL,0 ;置列属性
MOV BL,COLOR ;置颜色属性
MOV AL,CHAR ;置光标属性
MOV AH,13H
INT 10H
ENDM
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DISPCOL MACRO COL,NUM ;定义宏DISPCOL彩显若干个字符
MOV AH,9
MOV BH,0 ;置显示页
MOV BL,COL ;置颜色属性
MOV CX,NUM ;字符显示次数
INT 10H
ENDM
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WIN MACRO OPR1,OPR2,OPR3,OPR4,OPR5,OPR6 ;定义宏WIN建立窗口
MOV AH,06H ;功能号
MOV AL,OPR1 ;AL=0初始化或AL=上卷行数
MOV BH,OPR2 ;置卷入行属性
MOV CH,OPR3 ;置左上行
MOV CL,OPR4 ;置左上列
MOV DH,OPR5 ;置右上行
MOV DL,OPR6 ;置右上列
INT 10H
ENDM
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
POS_CURSE MACRO OP1,OP2,OP3 ;定义宏POS_CURSE光标位置
MOV AH,2
MOV BH,OP1 ;页号
MOV DH,OP2 ; 行
MOV DL,OP3 ; 列
INT 10H
ENDM
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;程序开始
DATA SEGMENT
X DB ?
Y DB ?
Z DW ?
W DW ?
COU DW ?
COUNT DW 0
SEC DW 0
MIN DW 0
HOURS DW 0
SAVE_LC DW 2 DUP(?)
DATE DB '2005/??/??','$' ;显示系统日期格式
SYSTIME DB '??:??:??$' ;显示系统时间格式
DAT1 DB 11 DUP(-1)
DAT2 DB 20 DUP(?)
RESULT DW 20 DUP(?)
FLAG DW 0
STR1 DB 0AH,0DH, '********************************************************************$'
LENSTR1 EQU $-STR1-1
STR2 DB 0AH,0DH, '** Program of Add and Subtract between 0 and 20 **$'
STR3 DB 0AH,0DH, '** Designed by Chengxiangchuang E_mail:cxc-0378@163.com **$'
STR4 DB 0AH,0DH, '** Computer 02-1 of Anhui University of Science & Technology **$'
STR5 DB 0AH,0DH, '********************************************************************$'
MESS1 DB 0DH,0AH,'Cost Time: $'
MESS2 DB 0DH,0AH,'You are Right! $'
LENMESS2 EQU $-MESS2-1
MESS5 DB 0DH,0AH,'Your Marks will add 10!$'
LENMESS5 EQU $-MESS5-1
MESS3 DB 0DH,0AH,'You are Wrong!$'
LENMESS3 EQU $-MESS3-1
MESS4 DB 0DH,0AH,'The Right Answer is: $'
LENMESS4 EQU $-MESS4-1
MESS6 DB 0DH,0AH,'Your Marks in total are: $'
LENMESS6 EQU $-MESS6-1
MESS7 DB 0DH,0AH,'Congratulation! You are Excellent! ^Q^ ^Q^ ^Q^ $'
LENMESS7 EQU $-MESS7-1
MESS8 DB 0DH,0AH,'Congratulation! You are Good! ^Q^ ^Q^ $'
LENMESS8 EQU $-MESS8-1
MESS9 DB 0DH,0AH,'How Lucky! You are just Passing! ^Q^ $'
LENMESS9 EQU $-MESS9-1
MESS10 DB 0DH,0AH,'Sorry! You are Not Passing! Come on!$'
LENMESS10 EQU $-MESS10-1
MESS11 DB 0DH,0AH,'Do you want to Test again? (Y/N) $'
LENMESS11 EQU $-MESS11-1
DATA ENDS
;==========================================================================================
STACK SEGMENT STACK
DB 200 DUP(0)
STACK ENDS
;==========================================================================================
CODE SEGMENT
MAIN PROC FAR
ASSUME CS:CODE,DS:DATA,SS:STACK
START: PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV ES,AX
MOV Y,0
MOV Z,0
MOV DI,0
MOV AH,0 ;设置25*80 彩色文本
MOV AL,3
INT 10H
MOV AH,35H ;将原中断保存在自设单元中
MOV AL,1CH
INT 21H
MOV SAVE_LC,BX
MOV SAVE_LC+2,ES
PUSH DS ;自设中断调用计数器
MOV DX,SEG CLINT
MOV DS,DX
MOV DX,OFFSET CLINT
MOV AL,1CH
MOV AH,25H
INT 21H
POP DS
IN AL,21H ;允许定时器中断
AND AL,11111110B
OUT 21H,AL
CALL SYSDATE ;调用系统日期
;CALL TIMECXC ;调用系统时间
DISPCOLOR STR1,LENSTR1,0,02H,1 ;显示CXC信息
DISPCOLOR STR2,LENSTR1,1,0CH,1
DISPCOLOR STR3,LENSTR1,2,0CH,1
DISPCOLOR STR4,LENSTR1,3,0CH,1
DISPCOLOR STR5,LENSTR1,4,02H,1
CALL CRLF
MOV COU,10 ;题目数为10
MOV W,1
MOV SI,1
BEGIN:
MOV COUNT,0 ;将时间各单元计数器,时,分,秒清0
MOV SEC,0
MOV MIN,0
MOV HOURS,0
RENEW1: MOV DI,W
CALL RAND ;第一个随机数
RENEW: CMP DAT1[DI],BL
JE RENEW1 ;比较随机数是否与原数组中数相等
DEC DI ;相等则再产生一个;不相等,则DI减1
JNE RENEW ;继续比较,不相等
JE NEXT ;直至DI为0,将随机数存至相应单元
NEXT: MOV DAT1[SI],BL
MOV DX,4000 ;时间延迟
AGAIN: MOV CX,65535
CXC: LOOP CXC
DEC DX
JNE AGAIN
CALL RAND ;第二个随机数
MOV DAT2,BL ;放到数组DAT2中
MOV AL,DAT1[SI] ;将第一个随机数存放到AL中
CMP FLAG,0 ;比较FLAG值
JE ADD1 ;FLAG=0,执行加法
JNE SUB1 ;FLAG=1,执行减法
ADD1:ADD AL,DAT2 ;计算两个随机数的和
CBW ;AL-->AX
MOV RESULT,AX ;保存AX-->RESULT
CMP AX,20 ;比较结果是否>20
JG BEGIN ;大于20重新来过
JMP ADD2
SUB1:SUB AL,DAT2 ;计算两个随机数的和
CBW ;AL-->AX
MOV RESULT,AX ;保存AX-->RESULT
CMP AX,0 ;比较结果是否<0
JL BEGIN ;<0重新来过
JMP SUB2
ADD2:MOV FLAG,1 ;FLAG置1,为减法作准备
DISPCOL 0DH,11 ;彩显算术式子
CALL SHOWQNUM ;输出题目序号
MOV BL,DAT1[SI] ;第一个随即数输出
CALL BINDEC ;二进制-->十进制
DISP1 '+' ;输出加号
JMP SHARE
SUB2:MOV FLAG,0 ;FLAG置0,为加法作准备
DISPCOL 0AH,11
CALL SHOWQNUM ;输出题目序号
MOV BL,DAT1[SI] ;第一个随即数输出
CALL BINDEC ;二进制-->十进制
DISP1 '-' ;输出减号
SHARE: MOV BL,DAT2 ;第2个随即数输出
CALL BINDEC ;二进制-->十进制
DISP1 '=' ;输出等号
CALL DECBIN ;键盘输入十进制-->二进制
CMP RESULT,BX ;比较键盘输入和计算结果是否相等
JE TRUE
JNE WRONG
TRUE:ADD Y,1
DISP MESS2 ;输出正确提示
DISP MESS5
JMP JP1
WRONG:
DISP MESS3 ;输出错误提示
DISP MESS4
;显示正确答案
MOV BX,RESULT
CALL BINDEC
JP1:
DISP MESS1 ;显示每道题所用时间
CALL DISPTIME
CALL CRLF
CALL CRLF
INC W
INC SI
DEC COU ;计数器减1,进入下一次循环
JNE BEGIN1
MOV X,10 ;计算总分
MOV AL,Y
MOV AH,0
MUL X
PUSH AX
DISPCOLOR MESS6,LENMESS6,24,03H,1 ;输出总分提示
POP AX ;输出总分
MOV BX,AX
CALL VALUE ;输出评语
CALL RETURN ;询问是否再作一遍试题
CALL SYSDATE ;调用系统日期
CALL TIMECXC ;调用系统时间
CLI ;恢复原中断
PUSH DS
MOV DX,SAVE_LC
MOV AX,SAVE_LC+2
MOV DS,AX
MOV AL,1CH
MOV AH,25H
INT 21H
POP DS
STI
RET
BEGIN1:JMP BEGIN
MAIN ENDP
;******************************************************************************************
RAND PROC NEAR ;产生随机数子程序
PUSH CX
PUSH DX
PUSH AX
STI ;置中断允许
MOV AH,0 ;读时钟计数器值
INT 1AH
MOV AX,DX
AND AH,3 ;清高6位
MOV DL,21 ;除21,产生0~20余数
DIV DL
MOV BL,AH ;余数存BX,作随机数
POP AX
POP DX
POP CX
RET
RAND ENDP
;******************************************************************************************
BINDEC PROC NEAR ;二进制-->十进制 (二位数)子程序
PUSH BX
PUSH CX
MOV CX,10 ;除以10
CALL DECDIV
MOV CX,1 ;除以1
CALL DECDIV
POP CX
POP BX
RET
BINDEC ENDP
;******************************************************************************************
DECDIV PROC NEAR ;二进制-->十进制(一位数)子程序
MOV AX,BX ;BX->AX,(DX,AX)作被除数,商->AX
MOV DX,0 ;DX清0,余数->DX
DIV CX ;CX存转换量级
MOV BX,DX
MOV DL,AL
ADD DL,30H
MOV AH,02 ;调用DOS(21H)2号功能
INT 21H
RET
DECDIV ENDP
;******************************************************************************************
DECBIN PROC NEAR ;十进制-->二进制子程序
MOV BX,0
NEWCHAR: MOV AH,1 ;键盘输入
INT 21H ;调用DOS(21H)1号功能
MOV DL,AL
SUB AL,30H ;ASCⅡ码-->二进制
JL EXIT ;是否<0
CMP AL,9
JG EXIT ;是否>9
CBW
XCHG AX,BX ;交换AX,BX
MOV CX,10
MUL CX
XCHG AX,BX
ADD BX,AX
JMP NEWCHAR
EXIT: RET
DECBIN ENDP
;******************************************************************************************
CRLF PROC NEAR ;回车换行子程序
MOV DL,0AH ;换行
MOV AH,02
INT 21H
MOV DL,0DH ;回车
MOV AH,02
INT 21H
RET
CRLF ENDP
;******************************************************************************************
BINDEC1 PROC NEAR ;二进制-->十进制(三位数)子程序
PUSH BX
PUSH CX
MOV CX,100
CALL DECDIV ;调用二进制->十进制(一位数)子程序
MOV CX,10
CALL DECDIV
MOV CX,1
CALL DECDIV
POP CX
POP BX
RET
BINDEC1 ENDP
;******************************************************************************************
VALUE PROC NEAR ;输出评语子程序
CMP BX,100
JE JP10
CMP BX,90
JE JP9
CMP BX,80
JE JP78
CMP BX,70
JE JP78
CMP BX,60
JE JP06
JB JP05
JP05: JMP JP5
JP06:JMP JP6
JP10:
CALL BINDEC1 ;100为三位数
DISPCOLOR MESS7,LENMESS7,24,04H,0 ;100为优秀
JMP RET1
JP9:
CALL BINDEC
DISPCOLOR MESS7,LENMESS7,24,04H,0 ;90也为优秀
JMP RET1
JP78:
CALL BINDEC
DISPCOLOR MESS8,LENMESS8,24,04H,0 ;70-80为良好
JMP RET1
JP6:
CALL BINDEC
DISPCOLOR MESS9,LENMESS9,24,04H,0 ;60为刚及格
JMP RET1
JP5:
CALL BINDEC
DISPCOLOR MESS10,LENMESS10,24,04H,0 ;60以下不及格
RET1:
RET
VALUE ENDP
;******************************************************************************************
RETURN PROC NEAR ;循环演练试题子程序
DISPCOLOR MESS11,LENMESS11,24,02H,1
MOV AH,01
INT 21H
CMP AL,'Y' ;输入Y或Y,再来一次
JE START1
CMP AL,'y'
JE START1
CMP AL,'N' ;输入N或N,及其他字符均返回
JE RET01
CMP AL,'n'
JE RET01
RET01:
CALL CRLF
;MOV AH,4CH
;INT 21H
RET
START1:JMP START
RETURN ENDP
;******************************************************************************************
SHOWQNUM PROC NEAR
DISP1 '(' ;输出左括号
ADD Z,1
MOV BX,Z ;输出题目序号
CALL BINDEC
DISP1 ')' ;输出右括号
DISP1 20H ;输出空格
RET
SHOWQNUM ENDP
;******************************************************************************************
TIMECXC PROC NEAR ;调用系统时间
DISPLAY: MOV AH,2CH
INT 21H
MOV BL,10
MOV AX,0
MOV AL,CH ;将CH中存放的"时"取出
DIV BL
ADD AX,3030H ;数字转化为字符
MOV [SYSTIME],AL ;存放至相应单元
MOV [SYSTIME+1],AH
MOV AX,0
MOV AL,CL ;将CL中存放的"分"取出
DIV BL
ADD AX,3030H
MOV [SYSTIME+3],AL ;存放至相应单元
MOV [SYSTIME+4],AH
MOV AX,0
MOV AL,DH ;将DH中存放的"秒"取出
DIV BL
ADD AX,3030H
MOV [SYSTIME+6],AL ;存放至相应单元
MOV [SYSTIME+7],AH
WIN 0,1DH,24,69,24,78 ;置显示背景及字体颜色属性
POS_CURSE 0,24,70 ;置光标属性
DISP SYSTIME
MOV BX,350
RE: MOV CX,33144 ;时间延迟
REA: LOOP REA
DEC BX
JNZ RE
JE DISPLAY
RET
TIMECXC ENDP
;******************************************************************************************
SYSDATE PROC NEAR ;显示系统日期
MOV AH,2AH
INT 21H
MOV BL,10D
MOV AX,0
MOV AL,DH ;将DH中存放的月份取出
DIV BL
ADD AX,3030H
MOV [DATE+5],AL ;存放至相应单元
MOV [DATE+6],AH
MOV AX,0
MOV AL,DL ;将DL中存放的日期取出
DIV BL
ADD AX,3030H
MOV [DATE+8],AL ;存放至相应单元
MOV [DATE+9],AH
WIN 0,2EH,0,69,0,78 ;置显示背景及字体颜色属性
POS_CURSE 0,0,69 ;置光标属性
MOV DX,OFFSET DATE
MOV AH,09H
INT 21H
RET
SYSDATE ENDP
;******************************************************************************************
CLINT PROC NEAR ;自设时间中断子过程
PUSH DS
PUSH BX
MOV BX,DATA
MOV DS,BX
LEA BX,COUNT
INC WORD PTR[BX]
CMP WORD PTR[BX],18 ;18次中断为1秒
JNE RETURN1
CALL INCT ;调用分秒转换子程序
ADJ:
CMP HOURS,12 ;处理"时"
JLE RETURN1
SUB HOURS,12
RETURN1:
POP BX
POP DS
STI
IRET
CLINT ENDP
;******************************************************************************************
INCT PROC NEAR ;分秒转换子程序
MOV WORD PTR[BX],0
ADD BX,2
INC WORD PTR[BX]
CMP WORD PTR[BX],60 ;60秒为1分
JNE EXIT1
CALL INCT
EXIT1: RET
INCT ENDP
;******************************************************************************************
DISPTIME PROC NEAR ;显示计时器时间
MOV AX,MIN ;显示"分"
CALL BINDECCXC1
MOV BX,0
MOV AL,':'
MOV AH,0EH
INT 10H
MOV AX,SEC ;显示"秒"
CALL BINDECCXC1
MOV BX,0
MOV AL,':'
MOV AH,0EH
INT 10H
MOV BX,COUNT ;显示"毫秒"
MOV AL,55
MUL BL
CALL BINDECCXC
RET
DISPTIME ENDP
;******************************************************************************************
BINDECCXC PROC NEAR ;为显示时间而服务的二进制->十进制(3位)
MOV CX,100
CALL DECDIVCXC
MOV CX,10
CALL DECDIVCXC
MOV CX,1
CALL DECDIVCXC
RET
BINDECCXC ENDP
;******************************************************************************************
BINDECCXC1 PROC NEAR ;为显示时间而服务的二进制->十进制(2位)
MOV CX,10
CALL DECDIVCXC
MOV CX,1
CALL DECDIVCXC
RET
BINDECCXC1 ENDP
;******************************************************************************************
DECDIVCXC PROC NEAR ;为显示时间而服务的二进制->十进制(1位)
MOV DX,0
DIV CX
MOV BX,0
ADD AL,30H
MOV AH,0EH
INT 10H
MOV AX,DX
RET
DECDIVCXC ENDP
;******************************************************************************************
CODE ENDS
END START
;☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
;☆ Designed by Chengxiangchuang | Http://Austjsj021.go.nease.net ☆
;☆ E_mail:cxc-0378@163.com | Copyright (C) 2005 Chengxiangchuang All Rights Reserved ☆
;☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
;信息统计:中文字数:2773;英文字符数:18667;总行数:615(我们寝室号)