沙发
hm1024 [专家分:220] 发布于 2006-01-16 09:25:00
;不通过中断来读取或设置时间,主要是读CMOS里的时间,通过70h,71h端口来实现,我编了一个,看看适合你不,已试过能够运行,你可以修改一下本机时间多试试。
;===============================================================================
;1、能被400整除是闰年。
;2、不能被100整除的,但能被4整除的是闰年。
;===============================================================================
;CMOS的读写完全靠 PORT 70h 和 71h 来读写其信息 ,其方法如下∶
;先 OUT 70h,Address
; 然后 IN AL,71h(读) 或 OUT 71h,AL(写)
; 其 Address 共有64bytes可用(即00-3Fh) ,各位意义可能是.....
; ^^^^^^
; 00 秒 (BCD码表示)
; 01 无用 (内容为00)
; 02 分 (BCD码表示)
; 03 无用 (内容为00)
; 04 时
; 05 无用 (内容为00)
; 06 不详
; 07 日
; 08 月
; 09 年
; 0A-0E 不详
; 0F Shadow states
; 10 Floppy A.B (NONE=0 ,360K=1 ,1.2MB=2 ,720K=3 ,1.44MB=4)
; 11 NONE
; 12 Hard Disk C.D (前面TYPE0Eh ,超过则搭配19-2Dh表示至TYPE4?)
; 13 NONE
; 14 配备
; 15&16 Base Memory
; 17&18 Memory
; 19-2D 无用...一般被拿来做 HD type 0E-4x
; 2E-2F CheckSum (只对某几个byte做CheckSum)
; 30&31 Memory
; 32 年代
; 33 刚开机为 01 ,无啥用处
; 34-3F 无用(常被拿来做User Type的信息 ,但最后几个byte仍没用到)
; 例如您想要读取时间 ,则下达
; out 70h,00
; in al,71h
; ===> al 即为时间值 (每次读取前请先 out 70h 一次)
; 如果您更改时间以外的值 ,请注意CheckSum ,以免下次开机会有
; CMOS Failure RUN SETUP ....
; 其中每种 BIOS 都会有某几个位未用到 ,于是就可拿来上保护罗,
; 但是请小心 ,如主机板电池没电就不适用此法.
; 例如您先执行
; out 70h,3fh
; out 71h,01h
; ===> 将CMOS没用的部份做一标志(01) ,以后只要
; out 70h,3fh
; in al,71h
; ===> 若 al=01 就代表合格 ,其它值不合格
; 可用任意值代替此标志 ,惟最好不要用 00h & 80h ,因为很多主机刚
; 开机设定完 CMOS ,此地方值即为上述值。
;===============================================================================
data segment
assume ds:data
date db 'Year-month-day hour:minute:second',0dh,0ah
db 'Now current date and time is:',24h
string1 db 0dh,0ah,'NO!',24h ;不是闰年
string2 db 0dh,0ah,'Yes!',24h ;是闰年
year dw ? ;保存年,如2006
flag db 0
data ends
code segment
assume cs:code
main proc near
mov ax,data
mov ds,ax
mov ah,09h ;显示字符串
mov dx,offset date
int 21h
mov al,32h ;输出年代
out 70h,al
in al,71h
call output1
mov byte ptr year + 1,al ;保存年的高两位,如果是2006年,那么这里保存的是20
mov al,09h ;输出年
out 70h,al
in al,71h
call output1
mov byte ptr year,al ;保存年的低两位,如06,等下用来计算是不是闰年
mov dl,'-' ;输出分格符 -
call output2
mov al,08h ;输出月
out 70h,al
in al,71h
call output1
mov dl,'-' ;输出分格符 -
call output2
mov al,07h ;输出日
out 70h,al
in al,71h
call output1
mov dl,' ' ;输出分格符两个空格
call output2
mov dl,' '
call output2
mov al,04h ;输出时
out 70h,al
in al,71h
call output1
mov dl,':' ;输出分格符 :
call output2
mov al,02h ;输出分
out 70h,al
in al,71h
call output1
mov dl,':' ;输出分格符 :
call output2
mov al,00h ;输出秒
out 70h,al
in al,71h
call output1
call years ;判断是不是闰年
cmp flag,0 ;不是闰年就跳转
je isnot
mov dx,offset string2 ;是闰年
jmp exit
isnot: mov dx,offset string1 ;不是闰年
exit: mov ah,09h
int 21h
mov ah,00h
int 16h
mov ah,4ch
int 21h
main endp
output1 proc near
push ax
push bx
push cx
mov bl,al ;由于CMOS中保存的数是BCD码,所以要转换一下
mov cl,4
shr al,cl
add al,30h
mov ah,02h
mov dl,al
int 21h
mov al,bl
and al,0fh
add al,30h
mov ah,02h
mov dl,al
int 21h
pop cx
pop bx
pop ax
ret
output1 endp
output2 proc near
mov ah,02h
int 21h
ret
output2 endp
years proc near
push ax
push bx
push cx
push dx
mov ax,word ptr year ;将BCD码2006年,转换成十六进制数7D6h
mov cx,4
rol ax,cl
push ax
and ax,0fh
mov bx,1000
mul bx
mov word ptr year,ax
pop ax
rol ax,cl
push ax
and ax,0fh
mov bx,100
mul bx
add word ptr year,ax
pop ax
rol ax,cl
push ax
and ax,0fh
mov bx,10
mul bx
add word ptr year,ax
pop ax
rol ax,cl
and ax,0fh
add word ptr year,ax
xor dx,dx ;判断能不能被400整除
mov ax,word ptr year
mov bx,400
div bx
cmp dx,0
jz setflag ;能被400整除则是闰年
xor dx,dx ;如果不能被400整除再看看能不能被4整除
mov ax,word ptr year ;如果能被4整除,但不能被100整除,那么
mov bx,4 ;也是闰年,例如2000年是闰年,2004年也是闰年
div bx
cmp dx,0
jz y_di100
mov flag,0
jmp y_exit
y_di100:xor dx,dx
mov ax,word ptr year
mov bx,100
div bx
cmp dx,0
jne setflag
mov flag,0
jmp y_exit
setflag:mov flag,1
y_exit :pop dx
pop cx
pop bx
pop ax
ret
years endp
code ends
end main