.286
.MODEL SMALL
.CODE
;-------数据段---------
CLOCK DB 8 DUP(?)
OLD1C LABEL DWORD ;旧1c中断
OLD1COFF DW ?
OLD1CSEG DW ?
oldint9 dd ?
time dw 91
oldint60 dd ?
oldint1c dd ?
;-----------------------
soundf proc
push dx
push ax
push cx
mov dx,10
in al,61h
and al,0fch
sound:
xor al, 02
out 61h, al
mov cx, 1400h
wait1:
loop wait1
dec dx
jne sound
pop cx
pop ax
pop dx
ret
soundf endp
;-----------------------
dispclock proc
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DS
mov cs:time, 18
LEA SI,CLOCK
MOV AH,02H
INT 1AH
MOV AH,CH
MOV AL,CL ;获取系统时间
MOV CL,4
SHR CH,CL
OR CH,30H
MOV DS:[SI],CH
INC SI ;送ascii码,小时 高位
MOV CH,AH
AND CH,0FH
OR CH,30H
MOV DS:[SI],CH
INC SI ;送ascii码,小时 低位
MOV DL,3AH
MOV DS:[SI],DL
INC SI ;冒号
MOV AH,AL
SHR AL,CL
OR AL,30H
MOV DS:[SI],AL
INC SI ;送ascii码,分钟 低位
MOV AL,AH
AND AL,0FH
OR AL,30H
MOV DS:[SI],AL
INC SI ;送ascii码,分钟 低位
MOV DS:[SI],DL
INC SI ;冒号
MOV AH,DH
SHR DH,CL
OR DH,30H
MOV DS:[SI],DH
INC SI
MOV DH,AH
AND DH,0FH
OR DH,30H
MOV DS:[SI],DH
INC SI ;秒
;push es
;push di
;mov ax, 0
;mov di, ax
;mov ax, 0b800h
;mov es, ax
;mov al, 20h
;mov ah, 07h
;mov cx, 2000
;cld
;rep stosw
;pop di
;pop es
mov ah, 6 ;清屏
mov al, 0
mov bh, 7
mov ch, 0
mov cl, 0
mov dh, 24
mov dl, 79
int 10h
LEA SI,CLOCK
PUSH ES
PUSH DI
MOV AX,072AH
MOV DI,AX
MOV AX,0B800H
MOV ES,AX ;采用写显存的方式输出
MOV CX,8 ;循环次数
MOV AH,34H ;属性值
DISP: PUSH CX
MOV AL,[SI]
INC SI
MOV CX,1
STOSW
POP CX
LOOP DISP
call soundf
quit:
cli
POP DI
POP ES
POP DS
POP SI
POP DX
POP CX
POP BX
POP AX
ret
dispclock endp
;-------------------------------------------------------------
newint60 proc far
sti
push ax
push dx
push ds
mov dx, cs:word ptr oldint9
mov ds, cs:word ptr oldint9[2]
mov ax, 2509h ;还原中断向量9
int 21h
mov dx, cs:word ptr oldint1c
mov ds, cs:word ptr oldint1c[2]
mov ax, 251ch ;还原中断向量1ch
int 21h
mov dx, cs:word ptr oldint60
mov ds, cs:word ptr oldint60[2]
mov ax, 2560h ;还原中断向量
int 21h
pop ds
pop dx
pop ax
iret
newint60 endp
;-----------------------
newint9 proc far
mov cs:time, 91
jmp cs:oldint9
newint9 endp
;-----------------------
newint1c PROC FAR
sti
mov al,20h
out 20h,al ;开中断
dec cs:time
jnz exit
call dispclock
EXIT: IRET
newint1c ENDP
prog_len EQU $-CLOCK
;---------------主程序---------------------------
INIT:
PUSH CS
POP DS
mov ax,351ch
int 21h
LEA DX,newint1c
CMP DX,BX
JE EX
lea di, oldint1c
mov word ptr [di], bx
mov word ptr [di+2], es
mov dx,offset newint1c
mov ax,seg newint1c
mov ds,ax
mov ax,251ch
int 21h
mov ax,3509h
int 21h
lea di, oldint9
mov word ptr [di], bx
mov word ptr [di+2], es
mov dx, offset newint9
mov ax, seg newint9
mov ds, ax
mov ax, 2509h
int 21h
mov ax,3560h
int 21h
lea di, oldint60
mov word ptr [di], bx
mov word ptr [di+2], es
mov dx,offset newint60
mov ax,seg newint60
mov ds,ax
mov ax,2560h
int 21h
;中断屏蔽(只响应计时器中断)
pop ds
in al,21h
and al,11111110b
out 21h,al
sti
;中断驻留
mov ah,31h
mov al,0
mov dx,((prog_len+15)/16)+16 ;驻留区大小
int 21h
EX:
MOV AH,4CH
INT 21H
END INIT
因为程序是几个月前写的,没什么注释,我现在也有点看不懂了,不过屏保程序的关键是键盘检测部分,要在键盘按下时,将计时器复位重新计时进入屏保。修改键盘中断int9,重写newint9为新键盘中断,在每次进入键盘中断的时候,先把计时器复位,然后程序跳转到原来int9的的部分,代码如下:
newint9 proc far
mov cs:time, 91
jmp cs:oldint9
newint9 endp
这样才能跳转到编辑目录。因为是程序中驻留了内存,每次只要程序出错,得强制关闭doxbox才能终止程序,于是根据内存驻留的原理,写了一个解除内存驻留的remove.exe
code segment
assume cs:code, ds:code
start:
jmp initialize
remove proc near
;mov al,60h
;mov ah,35h
;int 21h
;mov ax,es
;cmp ax,0
;jz done
int 60h
;push es
;mov ax, es:[2ch]
;mov es, ax
;mov ah, 49h ;解除环境块
;pop es
;mov ah, 49h ;解除程序块
;int 21h
done:ret
remove endp
initialize: call remove
mov ax, 4c00h
int 21h
code ends
end start