概述:
这个时钟程序是我在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 '> 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