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(我们寝室号)