?? clock.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 + -