ITEEDU

一个时钟程序

概述:

这个时钟程序是我在1993年编的一个小程序,现在贴出来给大家做参考,它执行后驻留内存,到整点时会报时,你可以用 Ctrl-Alt-U 把它从内存中下掉,可以用 Ctrl-Alt-C 变换颜色,用 Ctrl-Alt-O 把报时声音关掉(如果感到讨厌的话),在驻留内存时,用了直接改内存控制块的方法,所以用 MEM 或 MI 无法在内存中看到它,键盘控制用了直接截取 INT 9 的方法。
这个程序虽然很小,编译后才1K多一点点字节,但是麻雀虽小,五脏俱全,在这个程序中,你可以参考到以下编程方法:如何驻留内存;如何截取中断向量;如何在硬件层次上应答键盘;如何截取组合键。
由于时间有限,我就不把注释翻译成中文了,大家有空自己琢磨,本程序在引用时请注明出处,并请勿改动版权信息。

源程序:

; CLOCK program
; by LuoYunBin Apr,1993

           DISPLAY_COLOR  EQU       0EH         ;init color

        CODE  SEGMENT
              ASSUME    CS:CODE,DS:CODE
              ORG       0C0H

       CLOCK  DB        0
        MINU  DB        0
      SECOND  DB        0
   BEEP_TIME  DB        0
    LAST_SEC  DB        0
       OFF1C  DW        ?
       SEG1C  DW        ?
            DISPLAY_DATA  DB        0,0,':',0,0,':',0,0

              ORG       100H
      START:
              JMP       INSTALL
      INT1C:
              PUSHF
              PUSH      ES
              PUSH      DS
              PUSH      AX

              PUSH      CS
              POP       DS

              XOR       AX,AX
              MOV       ES,AX
              MOV       AL,ES:[0449H]           ;get display mode

              MOV       WORD PTR V_BUFFER-2,0B800H
              MOV       BYTE PTR CLOCK_PLACE-2,72*2

              CMP       AL,3        ;the clock may display
              JBE       TEXT_COLOR  ;at mode 0,1,2,3,7
              CMP       AL,7
              JZ        TEXT_MON
              MOV       WORD PTR V_BUFFER-2,ES
              JMP       SHORT CALU
 TEXT_COLOR:
              CMP       AL,1
              JA        CALU
              MOV       BYTE PTR CLOCK_PLACE-2,32*2
              JMP       SHORT CALU
   TEXT_MON:
              MOV       WORD PTR V_BUFFER-2,0B000H
       CALU:
              PUSH      BX
              PUSH      CX
              PUSH      DX
              PUSH      DI
              PUSH      SI

              MOV       CX,ES:[046EH]           ;get clock timers
              MOV       DX,ES:[046CH]

              MOV       AX,CX       ;counter=cx:dx
              MOV       BX,DX
              SHL       DX,1
              RCL       CX,1
              SHL       DX,1
              RCL       CX,1

              ADD       DX,BX
              ADC       AX,CX
              XCHG      DX,AX       ;dx:ax=cx:dx*5

              MOV       CX,0E90BH
              DIV       CX          ;divide by E90B*E90B

              MOV       BX,AX
              XOR       AX,AX
              DIV       CX

              MOV       DX,BX
              MOV       CX,00C8H
              DIV       CX

              CMP       DL,100
              JB        CLOCK_0

              SUB       DL,100
    CLOCK_0:
              CMC
              RCL       AX,1
              MOV       DL,0
              RCL       DX,1
              MOV       CL,60
              DIV       CX

              MOV       SECOND,DL
              DIV       CL

              MOV       MINU,AH
              MOV       CLOCK,AL
      CODE1:
              JMP       SHORT CODE2 ;when speaker on here is NOP

              DEC       BEEP_TIME   ;dec alarm time
              JZ        TURN_SP_OFF

              CMP       LAST_SEC,1  ;every 10 min's beep
              JZ        DAT0

              CMP       LAST_SEC,59 ;59 min 59 sec's beep
              JNZ       DAT1

              MOV       CL,6
              MOV       CH,3
              MOV       BX,800H
              JMP       SHORT DAT2
       DAT0:
              MOV       CL,3
              MOV       CH,2
              MOV       BX,200H
       DAT2:
              MOV       AL,BEEP_TIME
              XOR       AH,AH
              DIV       CL

              CMP       AH,CH
              JZ        SHORT SPEAK_ON1

              OR        AH,AH       ;after 1 count off
              JZ        DAT1

              IN        AL,61H
              AND       AL,0FCH
              OUT       61H,AL
       DAT1:
              JMP       SHORT DISP_CLOCK
            TURN_SP_OFF:
              IN        AL,61H
              AND       AL,0FCH
              OUT       61H,AL      ;turn off the speaker

              MOV       WORD PTR CODE1,-1       ;move code1 (jmp code2)
      CODE2:
              MOV       AL,AH       ;al is minute
              MOV       AH,DL       ;ah is second

              OR        AH,AH
              JZ        IS_SEC0

              CMP       AH,1
              JZ        IS_SEC1

              CMP       AL,59       ;59 min
              JNZ       DISP_CLOCK

              CMP       AH,59
              JNZ       DISP_CLOCK

              MOV       BEEP_TIME,15
              MOV       BX,800H
              JMP       SHORT SPEAK_ON
    IS_SEC1:
              MOV       LAST_SEC,0FFH
              JMP       SHORT DISP_CLOCK
    IS_SEC0:
              OR        AL,AL
              JZ        IS_MIN0

              MOV       CL,10       ;if is every 10 min
              DIV       CL
              OR        AH,AH
              JNZ       DISP_CLOCK

              MOV       CL,3
              MUL       CL
              DEC       AL
              MOV       BEEP_TIME,AL
              INC       AH
              MOV       BX,200H
              JMP       SHORT SPEAK_ON
    IS_MIN0:
              MOV       BEEP_TIME,18
              MOV       BX,400H
   SPEAK_ON:
              CMP       LAST_SEC,AH ;then not oprate
              MOV       LAST_SEC,AH
              JZ        DISP_CLOCK
  SPEAK_ON1:
              MOV       AL,0B6H
              OUT       43H,AL
              MOV       AX,BX
              OUT       42H,AL
              MOV       AL,AH
              OUT       42H,AL

              IN        AL,61H      ;turn on the speaker
              OR        AL,3
              OUT       61H,AL
              MOV       WORD PTR CODE1,9090H    ;move code1 (NOP)
 DISP_CLOCK:
              MOV       AL,CLOCK
              MOV       SI,OFFSET DISPLAY_DATA
              PUSH      SI
              CALL      HEX_TO_ASC  ;turn HEX to ASC II code
              MOV       AL,MINU
              CALL      HEX_TO_ASC
              MOV       AL,SECOND
              CALL      HEX_TO_ASC
              POP       SI
              CMP       BYTE PTR [SI],'0'
              JNZ       MOV_DATA

              MOV       BYTE PTR [SI],' '
   MOV_DATA:
              MOV       AX,0B800H   ;buffer segment
   V_BUFFER:
              OR        AX,AX
              JZ        I1CQUIT
              MOV       ES,AX
              MOV       DI,72*2
            CLOCK_PLACE:
              MOV       CX,8
              CLD
              MOV       AH,DISPLAY_COLOR        ;the color is yellow
      CODE3:
              JMP       SHORT IS_VGA

              MOV       DX,3DAH
     M_LOOP:
              IN        AL,DX
              TEST      AL,8
              JNZ       N3

              TEST      AL,1
              JNZ       M_LOOP
         N2:
              IN        AL,DX
              TEST      AL,1
              JZ        N2
         N3:
              LODSB
              STOSW
              LOOP      M_LOOP
              JMP       SHORT I1CQUIT
     IS_VGA:
              LODSB
              STOSW
              LOOP      IS_VGA
    I1CQUIT:
              POP       SI
              POP       DI
              POP       DX
              POP       CX
              POP       BX
              POP       AX
              POP       DS
              POP       ES
              POPF
              IRET

  HEX_TO_ASC  PROC      NEAR

              CBW
              MOV       CL,10
              DIV       CL

              ADD       AX,'00'
              MOV       DS:[SI],AX

              ADD       SI,3

              RET

  HEX_TO_ASC  ENDP

; new int 9 keyboard program
; Ctrl-Alt-U to unload
; C to change clock color
; B to change clock background color

       INT9:
              PUSHF
              PUSH      AX
              PUSH      DS
              XOR       AX,AX
              MOV       DS,AX
              MOV       AL,DS:[0417H]
              AND       AL,0CH
              CMP       AL,0CH
              JZ        CTRL_ALT_DOWN           ;if Ctrl-Alt press down
    TO_OLD9:
              POP       DS
              POP       AX
              POPF
              DB        0EAH
        OFF9  DW        ?
        SEG9  DW        ?

          CTRL_ALT_DOWN:
              IN        AL,60H
              CMP       AL,80H      ;if release key
              JAE       TO_OLD9
              CMP       AL,24       ;o key
              JZ        RIGHT_KEY
              CMP       AL,46       ;c key
              JZ        RIGHT_KEY
              CMP       AL,22       ;u key
              JZ        RIGHT_KEY
              CMP       AL,48       ;b key
              JNZ       TO_OLD9
  RIGHT_KEY:
              PUSH      AX
              IN        AL,61H
              MOV       AH,AL
              OR        AL,80H
              OUT       61H,AL
              XCHG      AH,AL
              OUT       61H,AL      ;answer the keyboard
              POP       AX

              CMP       AL,22       ;u key
              JZ        UN_LOAD

              PUSH      CS
              POP       DS
              CMP       AL,24       ;o key
              JZ        KEY_O
              CMP       AL,46       ;c key
              JZ        KEY_C

              MOV       AL,BYTE PTR CODE3-1     ;is "b" key:change back color
              MOV       AH,AL
              AND       AL,0F0H
              ADD       AL,10H
              CMP       AL,80H
              JNZ       BC_1
              XOR       AL,AL
       BC_1:
              AND       AH,0FH
              OR        AL,AH
              JMP       SHORT CHG_COLOR
      KEY_C:
              MOV       AL,BYTE PTR CODE3-1
              MOV       AH,AL
              AND       AL,0FH
              INC       AL
              CMP       AL,10H
              JNZ       FC_1
              XOR       AL,AL
       FC_1:
              AND       AH,0F0H
              OR        AL,AH
  CHG_COLOR:
              MOV       BYTE PTR CODE3-1,AL
              JMP       SHORT KEY_IRET
    UN_LOAD:
              PUSH      ES
              LES       AX,DWORD PTR CS:OFF9
              MOV       DS:[0024H],AX
              MOV       DS:[0026H],ES
              LES       AX,DWORD PTR CS:OFF1C
              MOV       DS:[0070H],AX
              MOV       DS:[0072H],ES
              PUSH      CS
              POP       AX
              DEC       AX
              MOV       DS,AX
              MOV       WORD PTR DS:[0001],0
              POP       ES
              JMP       SHORT KEY_IRET
      KEY_O:
              CMP       BYTE PTR INT1C,9CH      ;code of PUSHF
              JZ        TURN_OFF

              MOV       BYTE PTR INT1C,9CH
              JMP       SHORT KEY_IRET
   TURN_OFF:
              MOV       BYTE PTR INT1C,0CFH     ;code of IRET
   KEY_IRET:
              MOV       AL,20H
              OUT       20H,AL      ;send EOI command
              POP       DS
              POP       AX
              POPF
              IRET
    INSTALL:
              MOV       BYTE PTR DISPLAY_DATA+2,':'
              MOV       BYTE PTR DISPLAY_DATA+5,':'
              MOV       AX,WORD PTR CODE1
              MOV       WORD PTR CODE2-2,AX
              MOV       SI,81H
              MOV       BP,OFFSET INT9          ;bp is str point
              CLD
    RE_LOAD:
              LODSB
              CMP       AL,' '
              JZ        RE_LOAD
              CMP       AL,0DH
              JZ        COM_LINE_END
              CMP       AL,'?'
              JZ        HELP
              OR        AL,20H
              CMP       AL,'u'
              JZ        NO_KEY_INT
              CMP       AL,'h'
              JNZ       RE_LOAD
       HELP:
              MOV       DX,OFFSET D_HELP
              MOV       AH,9
              INT       21H
              INT       20H
           COM_LINE_END:
              CLC
              JMP       SHORT HAVE_KEY_INT
 NO_KEY_INT:
              STC
           HAVE_KEY_INT:
              PUSHF
              MOV       AX,351CH
              INT       21H
              MOV       OFF1C,BX
              MOV       SEG1C,ES
              CMP       BX,OFFSET INT1C
              JNZ       NOT_LOADED

              MOV       DX,OFFSET D_HAS
              MOV       AH,9
              INT       21H
              JMP       QUIT
 NOT_LOADED:
              POPF
              JC        SKIP_KEY
              MOV       AX,3509H
              INT       21H

              MOV       OFF9,BX
              MOV       SEG9,ES
              MOV       DX,OFFSET INT9
              MOV       AX,2509H
              INT       21H         ;set keyboard intrupter vector
              MOV       BP,OFFSET INSTALL
   SKIP_KEY:
              MOV       AX,251CH
              MOV       DX,OFFSET INT1C
              INT       21H         ;set clock interupter vector

              MOV       AH,0FH      ;if is MDA,color=09
              INT       10H
              CMP       AL,07H
              JNZ       IS_COLOR
              MOV       BYTE PTR DS:CODE3-1,09H
   IS_COLOR:
              MOV       AH,1BH      ;if is VGA,then not test snow
              XOR       BX,BX
              PUSH      CS
              POP       ES
              MOV       DI,OFFSET BUFFER
              INT       10H
              CMP       AL,1BH
              JZ        VGA_CARD
              MOV       WORD PTR DS:CODE3,9090H
   VGA_CARD:
              MOV       BX,BP
              ADD       BX,000FH
              SHR       BX,1
              SHR       BX,1
              SHR       BX,1
              SHR       BX,1
              MOV       AH,4AH
              INT       21H

              PUSH      CS
              POP       AX
              DEC       AX
              MOV       DS,AX
              MOV       WORD PTR DS:[0001H],0008H
       QUIT:
              INT       20H

      D_HELP  DB        '<<< CLOCK >>> Version 1.4',0DH,0AH
              DB        '(c)1995 By Luo Yun Bin of HuangYan post office.',0DH,0AH
              DB        'phone:0576-4114689',0DH,0AH
              DB        'BP: 0576-126 call 117654',0DH,0AH
              DB        'Usage:',0DH,0AH
              DB        9,'Ctrl-Alt-U: unload from memory.',0DH,0AH
              DB        9,'Ctrl-Alt-C: change color.',0DH,0AH
              DB        9,'Ctrl-Alt-B: change backgroud color.',0DH,0AH
              DB        9,'Ctrl-Alt-O: turn on/off.',0DH,0AH
              DB        '$'

       D_HAS  DB        'CLOCK has been installed!',0DH,0AH,'$'

      BUFFER  EQU       THIS BYTE

        CODE  ENDS
              END       START