⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.asm

📁 主程序中设置中断向量
💻 ASM
字号:
sta     segment STACK
        db      200h dup(?)
top     label   word
sta     ends

code    segment
        assume cs:code,ds:code,ss:sta
main    proc    far
        push    ds
        mov     ax,0
        push    ax
       
        mov     ax,seg NEWINT1C      
        mov     ds,ax                  ;DS指向代码段
        mov     dx,offset NEWINT1C     ;DX指向新中断入口地址
        mov     ax,251ch               ;中断类型号1c
        int     21h                    ;设置中断向量

        mov     ax,351ch
        int     21h                    ;测试新中断

        mov     ax,3100h
        int     21h                    ;终止并驻存内存
        ret
main    endp


CLOCK        DB    0
MINU         DB    0
SECOND       DB    0
BEEP_TIME    DB    0
LAST_SEC     DB    0
DISPLAY_DATA    DB    0,0,':',0,0,':',0,0


NEWINT1C proc  far
        pushf
        push   es
        push   ds
        push   ax
        push   bx
        push   cx
        push   dx
        push   di
        push   si

        xor    ax,ax
        mov    es,ax
        push   cs
        pop    ds

        mov    al,es:[0449h]         ;取显示模式
        mov    cx,es:[046eh]         ;取BIOS的时间
        mov    dx,es:[046ch]

        mov    ax,cx             ;取得的计数时间在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                
        mov    bx,ax
        xor    ax,ax
        div    cx                 ;以上几命令使dx:ax除以E90B的平方

        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         ;当扬声器打开时此处为空,使不转移向code2

        dec    beep_time         ;减少发声时间
        jz     turn_sp_off

        cmp    last_sec,1         ;每十分钟一次短响
        jz     dat0

        cmp    last_sec,59         ;每59分钟59秒一次短响加长响
        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             ;在报时一秒后停响
        jz     dat1

        in     al,61h             ;位触发方式发声
        and    al,0fch            ;关断定时器通道2的门控
        out    61h,al
dat1:
        jmp    short disp_clock
turn_sp_off:
        in     al,61h
        and    al,0fch
        out    61h,al             ;恢复61h端口,关掉扬声器

code2:
        mov    al,ah             ;把分钟数存到al中
        mov    ah,dl             ;把秒数存到ah中

        or     ah,ah            
        jz     is_sec0

        cmp    ah,1
        jz     is_sec1

        cmp    al,59             ;判断是否是在地59分钟
        jnz    disp_clock

        cmp    ah,59             ;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         ;是否是每十分钟响一次的模式
        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         ;是则不进行操作
        mov    last_sec,ah
        jz     disp_clock
speak_on1:
        mov    al,0b6h        ;位组合格式:通道2,两字节计数,模式3,二进制码
        out    43h,al         ;幻数方式寄存器
        mov    ax,bx          ;频率送到ax
        out    42h,al         ;频率计数值送通道2
        mov    al,ah
        out    42h,al

        in     al,61h             ;打开扬声器
        or     al,3
        out    61h,al
        mov    word ptr code1,9090h     ;使得code1地址处为空,而不跳到code2
disp_clock:
        mov    al,clock
        mov    si,offset display_data
        push   si
        call   hex_to_asc         ;使16进制数转为ASC II码输出
        mov    al,minu
        call   hex_to_asc
        mov    al,second
        call   hex_to_asc
        pop    si
        cmp    byte ptr [si],'0'  ;第一个数为‘0’则不输出
        jnz    mov_data

        mov    byte ptr [si],' '
mov_data:
        mov    ax,0b800h         ;缓冲区
v_buffer:
        or     ax,ax
        jz     i1cquit
        mov    es,ax
        mov    di,72*2
clock_place:
        mov    cx,8
        cld
        mov    ah,0eh     ;字体取黄色

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
NEWINT1C endp



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



code ends
end main

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -