DATA    SEGMENT
OP      DB ?
NUM1    DW ?
NUM2    DW ?
ANSWER  DW ?
SPA     DB 36 DUP(20H)
STRING  DB 20 DUP(?)
FLAGE   DW 0
PASS    DW 0
TOTAL   DW 0
RESULT  DB 29 DUP(20H),'Your accuracy is '
RATE    DB 10 DUP(20H)
BYE     DB 0DH,0AH,0DH,0AH,20 DUP(20H),'Thank you for using our system. Goodbye!','$'
TIPS1   DB 80 DUP(2AH),2AH,78 DUP(20H),2AH,2AH,78 DUP(20H),2AH,2AH,16 DUP(20H)
        DB 'Welcome To Use Calculations Training System!',18 DUP(20H),2AH
        DB  2AH,78 DUP(20H),2AH,2AH,78 DUP(20H),2AH,80 DUP(2AH),0DH,0AH,'$'
TIPS2   DB 'Press any key to practice and press SPACE to quit.',0DH,0AH,0DH,0AH,'$'
TIPS3   DB 0DH,0AH,'Press any key to continue and press SPACE to finish the exercise.',0DH,0AH,0DH,0AH,'$'
RIGHT   DB 160 DUP(20H),19 DUP(20H),'Congratulations, your answer is correct!',0DH,0AH,'$'
WRONG   DB 160 DUP(20H),12 DUP(20H),'Sorry, your answer is wrong! The correct answer is '
ANS     DB 8 DUP(20H)
DATA    ENDS
STACK   SEGMENT PARA STACK 'STACK'
STA     DB 80 DUP(?)
STACK   ENDS
CODE    SEGMENT
        ASSUME CS:CODE,DS:DATA,SS:STACK
START   PROC FAR
        PUSH DS
        MOV AX,0
        PUSH AX
        MOV AX,DATA
        MOV DS,AX
        MOV AX,03      ;清屏
        INT 10H	
        ;以下为改变字符颜色代码
        MOV CX,560
        MOV AH,09
        LEA BX,TIPS1
DISP1:  MOV AL,[BX]
        PUSH BX
        PUSH CX
        MOV BH,0
        MOV BL,10011100B  ;蓝底红字闪烁
        MOV CX,560
        INT 10H
        POP CX
        POP BX
        INC BX
        LOOP DISP1

        LEA DX,TIPS1
        CALL DISPLAY   ;显示欢迎语
        LEA DX,TIPS2
        CALL DISPLAY   ;显示提示
        MOV AH,07
        INT 21H        ;等待用户选择
        CMP AL,20H     ;输入是否为空格
        JE QUIT        ;是则退出程序
RE:     MOV BX,04
        CALL RAND      ;产生一个到之间随机数
        CMP AL,01
        JE MPLUS       ;若产生了则生成加法式
        CMP AL,02
        JE MMINUS      ;若产生了则生成减法式
        CMP AL,03
        JE MMULT       ;若产生了则生成乘法式
        CALL DIVIDE    ;若为则直接调用除法子程序
        JMP OUTP
MPLUS:  CALL PLUS      ;调用加法子程序
        JMP OUTP
MMINUS: CALL MINUS     ;调用减法子程序
        JMP OUTP
MMULT:  CALL MULT      ;调用乘法子程序
        JMP OUTP
OUTP:   CALL INPUT     ;调用用户输入结果子程序
        LEA DX,TIPS3
        CALL DISPLAY
        MOV AH,07
        INT 21H        ;等待用户选择
        PUSH AX
        MOV CX,0A00H
        MOV DX,124FH
        MOV BH,07H
        MOV AX,0609H
        INT 10H        ;将部分屏幕内容清除
        MOV AH,02H
        MOV BH,0
        MOV DX,0A00H
        INT 10H        ;重置光标位置
        POP AX
        CMP AL,20H     ;输入是否为空格
        JNE RE         ;不是则继续产生算式
        CALL ACCUR     ;是空格则调用计算正确率子程序
        LEA DX,BYE
        CALL DISPLAY
        MOV AH,07
        INT 21H        ;按任意键退出本程序
QUIT:   RET
START   ENDP


;-------------产生随机数子程序-------------
RAND    PROC NEAR
        MOV AX,BX
        MOV DX,41H     ;用中断计时器的H端口    
        OUT DX,AX      ;产生到BX值之间的随机数
        IN  AL,DX      ;将随机数送到AL
        RET
RAND    ENDP


;----------------加法子程序----------------
PLUS    PROC NEAR
        MOV BX,99      ;在到之间产生第一个加数
        CALL RAND
        MOV AH,0
        MOV NUM1,AX    ;将第一个加数存到NUM1
        CALL RAND      ;在到之间产生第二个加数
        MOV AH,0
        MOV NUM2,AX    ;将第一个加数存到NUM2
        MOV BX,NUM1
        ADD AX,BX      ;相加
        MOV ANSWER,AX  ;将和送到ANSWER
        MOV OP,'+'
        CALL CHANGE
        ;以下为改变字符颜色代码
        MOV CX,79
        MOV AH,09
        LEA BX,SPA
DISP2:  MOV AL,[BX]
        PUSH BX
        PUSH CX
        MOV BH,0
        MOV BL,00001010B  ;黑底绿字
        MOV CX,79
        INT 10H
        POP CX
        POP BX
        INC BX
        LOOP DISP2
        
        LEA DX,SPA
        CALL DISPLAY
        RET
PLUS    ENDP


;----------------减法子程序----------------
MINUS   PROC NEAR
        MOV BX,99      
        CALL RAND      ;在到之间产生差
        MOV AH,0
        MOV ANSWER,AX  ;将差存到ANSWER
        CALL RAND      ;在到之间产生减数
        MOV AH,0
        MOV NUM2,AX    ;将减数存到NUM2
        MOV BX,ANSWER
        ADD AX,BX      ;将差与减数相加得到被减数
        MOV NUM1,AX    ;将被减数存到NUM1
        MOV OP,'-'
        CALL CHANGE
        ;以下为改变字符颜色代码
        MOV CX,79
        MOV AH,09
        LEA BX,SPA
DISP3:  MOV AL,[BX]
        PUSH BX
        PUSH CX
        MOV BH,0
        MOV BL,00001010B  ;黑底绿字
        MOV CX,79
        INT 10H
        POP CX
        POP BX
        INC BX
        LOOP DISP3
        
        LEA DX,SPA
        CALL DISPLAY
        RET
MINUS   ENDP


;----------------乘法子程序----------------
MULT    PROC NEAR
        MOV BX,99      ;在到之间产生第一个乘数
        CALL RAND
        MOV AH,0
        MOV NUM1,AX    ;将第一个乘数存到NUM1
        CALL RAND      ;在到之间产生第二个乘数
        MOV AH,0
        MOV NUM2,AX    ;将第一个乘数存到NUM2
        MOV BX,NUM1
        MUL BX         ;相乘
        MOV ANSWER,AX  ;将积送到ANSWER
        MOV OP,'*'
        CALL CHANGE
        ;以下为改变字符颜色代码
        MOV CX,79
        MOV AH,09
        LEA BX,SPA
DISP4:  MOV AL,[BX]
        PUSH BX
        PUSH CX
        MOV BH,0
        MOV BL,00001010B  ;黑底绿字
        MOV CX,79
        INT 10H
        POP CX
        POP BX
        INC BX
        LOOP DISP4
        
        LEA DX,SPA
        CALL DISPLAY
        RET
MULT    ENDP


;----------------除法子程序----------------
DIVIDE  PROC NEAR
        MOV BX,99      ;在到之间产生商
        CALL RAND
        MOV AH,0
        MOV ANSWER,AX  ;将商存到ANSWER
        CALL RAND      ;在到之间产生除数
        MOV AH,0
        MOV NUM2,AX    ;将除数存到NUM2
        MOV BX,ANSWER
        MUL BX         ;将商与除数相乘得到被除数
        MOV NUM1,AX    ;将被除数送到NUM1
        MOV OP,'/'
        CALL CHANGE
        ;以下为改变字符颜色代码
        MOV CX,79
        MOV AH,09
        LEA BX,SPA
DISP5:  MOV AL,[BX]
        PUSH BX
        PUSH CX
        MOV BH,0
        MOV BL,00001010B  ;黑底绿字
        MOV CX,79
        INT 10H
        POP CX
        POP BX
        INC BX
        LOOP DISP5
        
        LEA DX,SPA
        CALL DISPLAY
        RET
DIVIDE  ENDP


;-----------数据转换为字符子程序-----------
CHANGE  PROC NEAR
        MOV DX,'$'     ;将结束符入栈
        PUSH DX 
        MOV DX,'='     ;将等号入栈
        PUSH DX
        MOV BX,0AH     ;除数
        MOV CX,3
        MOV DX,0
        MOV AX,NUM2    ;将第二个操作数送AX
MARK1:  CMP AX,0
        JE  OVER1
        DIV BX         ;除取余
        ADD DX,30H     ;加H转换为ASCⅡ码
        PUSH DX        ;将ASCⅡ码入栈
        INC CX         ;计数器加
        MOV DX,0
        JMP MARK1
OVER1:  MOV DL,OP      
        PUSH DX        ;将运算符入栈
        MOV DX,0
        MOV AX,NUM1    ;将第一个操作数送AX
MARK2:  CMP AX,0
        JE  OVER2
        DIV BX         ;除取余
        ADD DX,30H     ;加H转换为ASCⅡ码
        PUSH DX        ;将ASCⅡ码入栈
        INC CX         ;计数器加
        MOV DX,0
        JMP MARK2
OVER2:  LEA BX,STRING
MARK3:  POP DX         ;将ASCⅡ码出栈
        MOV [BX],DX    ;将ASCⅡ码依次送STRING单元
        INC BX
        LOOP MARK3
        MOV BX,0AH     ;除数
        MOV CX,01      ;计数器初值为
        MOV DX,24H
        PUSH DX        ;将结束符入栈
        MOV AX,ANSWER
MARK12: MOV DX,0
        CMP AX,0
        JE OVER6
        DIV BX         ;除十取余
        ADD DX,30H     ;加H得到ASCⅡ码
        PUSH DX        ;将ASCⅡ码入栈
        INC CX         ;计数器加一
        JMP MARK12
OVER6:  CMP CX,01
        JNE MARK13
        MOV DX,30H
        PUSH DX        ;若答案为零,将H入栈
        INC CX
MARK13: LEA BX,ANS
MARK14: POP DX         ;将ANSWER字符依次出栈
        MOV [BX],DX    ;将ANSWER字符依次存到ANS单元
        INC BX
        LOOP MARK14
        RET
CHANGE  ENDP


;--------------用户输入并判断对错子程序------------
INPUT   PROC NEAR
        MOV CX,0
MARK4:  MOV AH,01      ;01功能调用,输入字符
        INT 21H
        CMP AL,0DH     ;输入是否为回车
        JE  OVER3      ;是则表示输入结束
        CMP AL,08
        JE DELETE
        MOV AH,0
        SUB AX,30H     ;字符的ASCⅡ码减H
        PUSH AX        ;将结果入栈
        INC CX         ;计数器加一
        JMP MARK4
DELETE: MOV AH,02
        MOV DL,08H
        INT 21H
        JMP MARK4
OVER3:  MOV AX,ANSWER
MARK5:  MOV DX,0
        MOV BX,0AH     ;除数
        DIV BX         ;除
        POP BX
        CMP DX,BX      ;将输入结果与正确答案比较
        JE MARK6
        MOV BX,0FFH
        MOV FLAGE,BX   ;与正确答案不同则将FLAGE置FFH
MARK6:  LOOP MARK5
        CMP AX,0
        JE MARK10
        MOV BX,0FFH
        MOV FLAGE,BX
MARK10: MOV AX,FLAGE
        CMP AX,0FFH    ;查看FLAGE是否为FFH
        JE MARK7
        ;以下为改变字符颜色代码
        MOV CX,219
        MOV AH,09
        LEA BX,RIGHT
DISP6:  MOV AL,[BX]
        PUSH BX
        PUSH CX
        MOV BH,0
        MOV BL,00001010B  ;黑底绿字
        MOV CX,219
        INT 10H
        POP CX
        POP BX
        INC BX
        LOOP DISP6
        
        LEA DX,RIGHT
        CALL DISPLAY   ;不是则显示正确提示
        MOV AX,PASS
        INC AX         ;正确题数加一
        MOV PASS,AX
        JMP OVER4
MARK7:  MOV CX,240     ;以下为改变字符颜色代码
        MOV AH,09
        LEA BX,WRONG
DISP7:  MOV AL,[BX]
        PUSH BX
        PUSH CX
        MOV BH,0
        MOV BL,00001100B  ;黑底红字
        MOV CX,240
        INT 10H
        POP CX
        POP BX
        INC BX
        LOOP DISP7
        
        LEA DX,WRONG
        CALL DISPLAY   ;是则显示错误提示
        MOV AH,02
        MOV DL,0DH
        INT 21H
        MOV DL,0AH
        INT 21H        ;换行
        MOV AX,0
        MOV FLAGE,AX   ;将FLAGE清零
OVER4:  MOV AX,TOTAL
        INC AX         ;总题数加一
        MOV TOTAL,AX
        RET
INPUT   ENDP

;-------------计算正确率子程序------------
ACCUR   PROC NEAR
        MOV CX,2
        MOV AX,PASS    ;做对题数送AX
        MOV BX,64H
        MUL BX         ;乘于
        MOV BX,TOTAL   ;所做总题数送BX
        DIV BX         ;计算正确率
        MOV DX,24H
        PUSH DX        ;将结束符入栈
        MOV DX,25H
        PUSH DX        ;将百分号入栈
        MOV DX,0
        MOV BX,0AH     ;除数
MARK8:  CMP AX,0       
        JE OVER5
        DIV BX         ;除取余
        ADD DX,30H     ;加H得到ASCⅡ码
        PUSH DX        ;将ASCⅡ码入栈
        INC CX         ;计数器加一
        MOV DX,0
        JMP MARK8
OVER5:  CMP CX,02
        JNE MARK11
        MOV DX,30H
        PUSH DX        ;无做对题将零的ASCⅡ码入栈
        INC CX
MARK11: LEA BX,RATE
MARK9:  POP DX
        MOV [BX],DX    ;将正确率的ASCⅡ码存RATE单元
        INC BX
        LOOP MARK9
        ;以下为改变字符颜色代码
        MOV CX,52
        MOV AH,09
        LEA BX,RESULT
DISP8:  MOV AL,[BX]
        PUSH BX
        PUSH CX
        MOV BH,0
        MOV BL,00001010B  ;黑底绿字
        MOV CX,52
        INT 10H
        POP CX
        POP BX
        INC BX
        LOOP DISP8
        
        LEA DX,RESULT
        CALL DISPLAY   ;显示正确率
        RET
ACCUR   ENDP

;----------------显示子程序---------------
DISPLAY PROC NEAR
        MOV AH,09
        INT 21H
        RET
DISPLAY ENDP

CODE    ENDS
        END  START

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据