📄 clock.asm
字号:
TYPE12 EQU 12 ;12小时型时钟
TYPE24 EQU 24 ;24小时型时钟
Z8279 EQU 212H ;控制口地址,写:命令,读:状态
D8279 EQU 210H ;数据口地址,写:显示,读:键盘
LEDMOD EQU 00H ;左边输入,八位显示外部译码八位显示
LEDFEQ EQU 38H ;扫描频率
TIM_CTL EQU 22bH ;定时器控制口
TIMER0 EQU 228H ;定时器0数据口
TIMER1 EQU 229H ;定时器1数据口
MODE03 EQU 00110110B ;定时器0方式3
MODE10 EQU 01110000B ;定时器1方式0
Time0Const EQU 5000
Time1Const EQU 5
INT00 EQU 200h
INT01 EQU 201h
BLANK EQU 01000000B ;字符闪烁属性
DOT EQU 10000000B ;显示点的属性
TIMESHOW EQU 0 ;正常时钟显示状态
TIMESET EQU 1 ;时间设置状态
TYPESET EQU 2 ;时钟模式改变状态
CODE SEGMENT
ASSUME CS:CODE,DS:CODE
START:
Push Cs
Pop Ds
CALL Init ;初始化
Call Clear
Call Display
Again:
Cmp ClockStatus,TIMESHOW ;如果正常时钟显示状,则显示时间
Jne Again1
Call TimePut
Again1:
Call Display
Call ReadKey
Jnc Again
Call KeyCmdProc
Jmp Again
;键盘命令处理子程序
;
;
KeyCmdProc Proc
Test Al,80H
Jz KeyN ;数字键按下跳转
Cmp Al,80H
Jz KeyA ;A键按下跳转
Cmp Al,81H
Jz KeyB ;B键按下跳转
Cmp Al,82h
Jz KeyC ;C键按下跳转
Cmp Al,83h
Jz KeyD ;D键按下跳转
Cmp Al,84h
Jz KeyE ;E键按下跳转
Cmp Al,85h
Jz KeyF ;F键按下跳转
Cmp Al,86H
Jz KeyG ;.键按下跳转
Cmp Al,87H
Jz KeyH ;,键按下跳转
Cmp Al,88h
Jz KeyI ;-键按下跳转
Cmp Al,89h
Jz KeyJ ;+键按下跳转
Cmp Al,8Ah
Jz KeyK ;:键按下跳转
Cmp Al,8Bh
Jz KeyL ;REG键按下跳转
Ret
KeyN: Call NumKey
Ret
KeyA: Call SetTime
Ret
KeyB: Call ChangeType
Ret
KeyC:
Ret
KeyD:
Ret
KeyE: Call Cancel
Ret
KeyF: Call Confirm
Ret
KeyG:
Ret
KeyH:
Ret
KeyI: Call LeftMove
Ret
KeyJ: Call RightMove
Ret
KeyK:
Ret
KeyL:
Ret
KeyCmdProc Endp
;设置时钟类型
;
;
ChangeType Proc
Cmp ClockStatus,TYPESET
Je ChangeType1
Mov ClockStatus,TYPESET
Call Clear
Mov Ah,13H ;设置提示符P,表示进入设置状态。
Mov Al,00h
Mov Bx,0
Call SetChar
Mov Al,ClockType
ChangeType0:
Call NtoS
Mov Cx,Ax
Mov Al,00h
Mov Bx,3
Call SetChar
Mov Ah,Cl
Mov Bx,2
Call SetChar
Jmp ChangeTypeRet
ChangeType1:
Mov Ah,DispBuffer+2*2
Mov Al,DispBuffer+3*2
Call CharToNum
Cmp Al,TYPE12
Je ChangeType2
Mov Al,TYPE12
Jmp ChangeType0
ChangeType2:
Mov Al,TYPE24
Jmp ChangeType0
ChangeTypeRet:
Ret
ChangeType Endp
;+键处理子程序
;
RightMove Proc
Cmp ClockStatus,TIMESET
Je RightMoveTimeSet
Jmp RightMoveRet
RightMoveTimeSet:
Mov Bx,DigPos
Inc Bx
Mov Al,BLANK
Call ClrCharAttr
Cmp DigPos,5
Jnz RightMoveTimeSet1
Mov DigPos,-1
RightMoveTimeSet1:
Inc DigPos
Mov Bx,DigPos
Inc Bx
Mov Al,BLANK
Call SetCharAttr
RightMoveRet:
Ret
RightMove Endp
;-键处理子程序
;
LeftMove Proc
Cmp ClockStatus,TIMESET
Je LeftMoveTimeSet
Jmp LeftMoveRet
LeftMoveTimeSet:
Mov Bx,DigPos
Inc Bx
Mov Al,BLANK
Call ClrCharAttr
Cmp DigPos,0
Jnz LeftMoveTimeSet1
Mov DigPos,6
LeftMoveTimeSet1:
Dec DigPos
Mov Bx,DigPos
Inc Bx
Mov Al,BLANK
Call SetCharAttr
LeftMoveRet:
Ret
LeftMove Endp
;数字键处理子程序
;
NumKey Proc
Cmp ClockStatus,TIMESET
Je NumkTimeSet
Jmp NumKeyRet
NumkTimeSet:
Cmp DigPos,0
Jne NumkTimeSetNext1
Cmp Al,3 ;时的十位只能是 0,1,2
Jc NumKTimeSetNext0
Jmp NumKeyRet
NumKTimeSetNext0:
Mov Ah,Al
Mov Bx,1
Mov Al,00h
Call SetChar
Jmp NumkTimeSetEnd
NumkTimeSetNext1:
Cmp DigPos,1
Jne NumkTimeSetNext2
Cmp DispBuffer+2,2
Jne NumkTimeSetNext11
Cmp Al,5 ;时的十位是2时,各位只能是0-4
Jc NumkTimeSetNext11
Jmp NumKeyRet
NumkTimeSetNext11:
Mov Ah,Al
Mov Bx,2
Mov Al,80h
Call SetChar
Jmp NumkTimeSetEnd
NumkTimeSetNext2:
Cmp DigPos,2
Jne NumkTimeSetNext3
Cmp Al,6 ;分钟的十位只能是 0-5
Jnc NumKeyRet
Mov Ah,Al
Mov Bx,3
Mov Al,00h
Call SetChar
Jmp NumkTimeSetEnd
NumkTimeSetNext3:
Cmp DigPos,3
Jne NumkTimeSetNext4
Mov Ah,Al ;分钟的个位可以是 0-9
Mov Bx,4
Mov Al,80h
Call SetChar
Jmp NumkTimeSetEnd
NumkTimeSetNext4:
Cmp DigPos,4
Jne NumkTimeSetNext5
Cmp Al,6 ;秒的十位只能是 0-5
Jnc NumKeyRet
Mov Ah,Al
Mov Bx,5
Mov Al,00h
Call SetChar
Jmp NumkTimeSetEnd
NumkTimeSetNext5:
Mov Ah,Al ;秒的个位可以是 0-9
Mov Bx,6
Mov Al,80h
Call SetChar
NumkTimeSetEnd:
Mov Bx,DigPos ;本位的闪烁数字改为不闪烁
Inc Bx
Mov Al,BLANK
Call ClrCharAttr
Cmp DigPos,5 ;计算下一个位置
Jnz NumkTimeSet1
Mov DigPos,-1
NumkTimeSet1:
Inc DigPos ;下一位数字闪烁
Mov Bx,DigPos
Inc Bx
Mov Al,BLANK
Call SetCharAttr
NumKeyRet:
Ret
NumKey Endp
;设置时间子程序
;
SetTime Proc
Mov ClockStatus,TIMESET ;状态改为时间设置。
Mov Ah,13H ;设置提示符P,表示进入时间设置状态。
Mov Al,00h
Mov Bx,0
Call SetChar
Mov DigPos,0
Mov Bx,DigPos
Inc Bx
Mov Al,BLANK
Call SetCharAttr
Ret
SetTime Endp
;设置确认子程序
;
Confirm Proc
Cmp ClockStatus,TIMESET
Je Confirm1
Cmp ClockStatus,TYPESET
Je Confirm2
Jmp ConfirmRet
Confirm1: ;时间设置确认
Cli
Mov Ah,DispBuffer+1*2
Mov Al,DispBuffer+2*2
Call CharToNum
Mov Hour,Al
Mov Ah,DispBuffer+3*2
Mov Al,DispBuffer+4*2
Call CharToNum
Mov Minute,Al
Mov Ah,DispBuffer+5*2
Mov Al,DispBuffer+6*2
Call CharToNum
Mov Second,Al
Sti
Mov ClockStatus,TIMESHOW
Jmp ConfirmRet
Confirm2: ;时钟显示类型确认
Mov Ah,DispBuffer+2*2
Mov Al,DispBuffer+3*2
Call CharToNum
Mov ClockType,Al
Mov ClockStatus,TIMESHOW
Jmp ConfirmRet
ConfirmRet:
Ret
Confirm Endp
;操作放弃子程序
;
Cancel Proc
Mov ClockStatus,TIMESHOW ;将状态设为TIMESHOW
Ret
Cancel Endp
;字符转数字子程序
;输入参数: AH:高位,AL:低位
;输出参数: AL:数
CharToNum Proc
Push Bx
Shl Ah,1
Mov Bh,Ah
Shl Ah,1
Shl Ah,1
Add Ah,Bh
Add Al,Ah
Pop Bx
Ret
CharToNum Endp
;数转2位字符串
;输入Al
;输出Ah:个位
; Al:十位
;影响Ax
NtoS Proc
Push Bx
Mov Ah,0
Mov Bl,10
Div Bl
Pop Bx
Ret
NtoS Endp
;置字符子程序
;输入参数 AH:字符,AL:属性,BX:位置
;输出参数:无
SetChar Proc
Push Bx
Shl Bx,1
Mov DispBuffer[Bx],Ah
Inc Bx
Mov DispBuffer[Bx],Al
Pop Bx
Ret
SetChar Endp
;置字符属性子程序
;输入参数 AL:属性,BX:位置
;输出参数:无
SetCharAttr Proc
Push Bx
Shl Bx,1
Inc Bx
Or DispBuffer[Bx],Al
Pop Bx
Ret
SetCharAttr Endp
;清字符属性子程序
;输入参数 AL:属性,BX:位置
;输出参数:无
ClrCharAttr Proc
Push Ax
Push Bx
Shl Bx,1
Inc Bx
Not Al
And DispBuffer[Bx],Al
Pop Bx
Pop Ax
Ret
ClrCharAttr Endp
;中断子程序
;十分之一秒中断子程序
;
Time Proc
Push Ax
Push Bx
Push Cx
Push Dx
Push Si
Push Di
MOV DX,TIMER1 ;定时器1常数设置
MOV Ax,Time1Const
OUT DX,AL
MOV Al,Ah
OUT Dx,Al
Cmp Second1,9 ;十分之一秒加一
Jz Time1
Inc Second1
Jmp Time5
Time1: Mov Second1,0 ;秒加一
Cmp Second,59
Jz Time2
Inc Second
Jmp Time5
Time2: Mov Second,0 ;分钟加一
Cmp Minute,59
Jz Time3
Inc Minute
Jmp Time5
Time3: Mov Minute,0 ;小时加一
Cmp Hour,23
Jz Time4
Inc Hour
Jmp Time5
Time4: Mov Hour,0 ;
Time5:
MOV DX,INT00
MOV AL,20H
OUT DX,AL
Pop Di
Pop Si
Pop Dx
Pop Cx
Pop Bx
Pop Ax
IRet
Time Endp
;读键盘子程序
;输入参数:无
;输出参数:CF=1 Al:键值
; CF=0 无键
;影响寄存器:Al
Readkey Proc
Push Bx
Push Cx
Push Dx
MOV Dx, Z8279 ;8279控制口地址
ReadKey1:
IN Al, Dx
;Test Al,80h
;Jz ReadKey1
TEST AL, 07H ;测试最低3位,确定有无键盘输入
JZ ReadKeyNo
MOV Dx, D8279 ;从数据端口读取按键的扫描码
IN Al, DX
Cmp Al,0Ah
Jc ReadkeyRet
Mov Bx,0
Mov Cx,12
Readkey2:
Cmp Al,ScanCode2[Bx]
Jz Readkey3
Inc Bx
Loop ReadKey2
Readkey3:
Mov Al,Bl
Or Al,80h
Stc
Jmp ReadKeyRet
ReadKeyNo:
Clc
ReadkeyRet:
Pop Dx
Pop Cx
Pop Bx
Ret
Readkey Endp
;显示子程序
;将显示缓冲区的内容在显示器上显示
;无数人输出
;不影响任何寄存器
Display Proc
push Ax
Push Bx
Push Cx
Push Dx
Push Si
Mov Cx,8
Mov Bx,15
Display1:
Xor Ax,Ax
Dec Bx
Mov Al,DispBuffer[Bx]
Mov Si,Ax
Mov Al,LED[Si]
Inc Bx
Mov Ah,DispBuffer[Bx]
Sub Bx,2
Test Ah,BLANK
Jz Display2
Cmp Second1,5
Jc Display2
Mov Al,00h
Display2:
Mov Dx,D8279
And Ah,80h
Or Al,Ah
Out Dx,Al
Loop Display1
Pop Si
Pop Dx
Pop Cx
Pop Bx
Pop Ax
Ret
Display Endp
;清显示器
;输入参数:无
;输出参数:无
;影响寄存器:无
Clear Proc
Push Bx
Push Cx
Mov Bx,0
Mov Cx,8
Clear1:
Mov Word ptr DispBuffer[Bx],0010H
Add Bx,2
Loop Clear1
Pop Cx
Pop Bx
Ret
Clear Endp
;输出时钟
TimePut Proc
Cmp Hour,TYPE12
Jnc TimePutpm
Mov Dispbuffer,11h
Jmp TimePut1
TimePutpm:
Mov Dispbuffer,12h
TimePut1:
Mov DispBuffer+1,00h
Cmp ClockType,TYPE24
Jz TimePut24
TimePut12:
Mov Al,Hour
Cmp Al,13
Jc TimePut24
Sub Al,12
Jmp TimePut241
TimePut24:
Mov Al,Hour
TimePut241:
Call NtoS
Mov DispBuffer+1*2,al
Mov DispBuffer+1*2+1,00h
Mov DispBuffer+2*2,ah
Mov DispBuffer+2*2+1,DOT
TimePut2:
Mov Al,Minute
Call NtoS
Mov DispBuffer+3*2,al
Mov DispBuffer+3*2+1,00h
Mov DispBuffer+4*2,ah
Mov DispBuffer+4*2+1,DOT
Mov Al,Second
Call NtoS
Mov DispBuffer+5*2,al
Mov DispBuffer+5*2+1,00h
Mov DispBuffer+6*2,ah
Mov DispBuffer+6*2+1,DOT
Mov Al,Second1
Mov DispBuffer+7*2,10h
Mov DispBuffer+7*2+1,00h
;Or DispBuffer+0*2+1,BLANK
;Or DispBuffer+1*2+1,BLANK
;Or DispBuffer+2*2+1,BLANK
;Or DispBuffer+3*2+1,BLANK
;Or DispBuffer+4*2+1,BLANK
;Or DispBuffer+5*2+1,BLANK
;Or DispBuffer+6*2+1,BLANK
;Or DispBuffer+7*2+1,BLANK
Ret
TimePut Endp
;初始化子程序
Init Proc
CLI
MOV AL,13H ;ICW1:边沿触发,单片,要ICW4
MOV DX,INT00
OUT DX,AL
MOV AL,8 ;中断号从8开始
MOV DX,INT01
OUT DX,AL
MOV Cx,0fffh
l00: LOOP l00
MOV AL,9 ;全嵌套方式,86/88系统
MOV DX,INT01
OUT DX,AL
MOV Cx,0fffh
l01: LOOP l01
MOV DX,INT01
MOV AL,00H ;八个中断全部开放
OUT DX,AL
MOV Cx,0fffh
l02: LOOP l02
MOV DX,INT00
MOV AL,20H ;非特殊EOI结束中断
OUT DX,AL
MOV Cx,0fffh
l03: LOOP l03
MOV DX,Z8279 ;8279初始化为 左边输入,八位显示外部译码八位显示
MOV AL,LEDMOD
OUT DX,AL
MOV AL,LEDFEQ ;8279的扫描频率
OUT DX,AL
MOV DX,TIM_CTL ;定时器0工作在方式3
MOV AL,MODE03
OUT DX,AL
MOV DX,TIMER0
MOV Ax,Time0Const
OUT DX,AL
MOV Al,Ah
OUT Dx,Al
MOV DX,TIM_CTL ;定时器1工作在方式0
MOV AL,MODE10
OUT DX,AL
MOV DX,TIMER1
MOV Ax,Time1Const
OUT DX,AL
MOV Al,Ah
OUT Dx,Al
MOV AX,0H ;设置中断向量
MOV ES,AX
MOV Word ptr Es:[0020h],Offset Time
MOV Word ptr Es:[0022h],8100h
STI
Ret
Init Endp
ClockStatus DB TIMESHOW
ClockType DB TYPE24 ;时钟类型
Hour DB 11 ;小时
Minute DB 59 ;分钟
Second DB 50 ;秒
Second1 DB 0 ;十分之一秒
DigPos DW 0 ;时钟设置时使用,0:小时十位,1:小时各位,2:分钟十位,3:分钟各位,4:秒十位,5:秒各位
ScanCode1 DB 00h,01h,02h,03h,04h,05h,06h,07h,08h,09h ;键盘扫描码
ScanCode2 DB 0ah,0bh,0ch,0dh,0eh,0fh,10h,11h,12h,13h,14h,15h ;键盘扫描码
DispBuffer DB 11h,00h,12h,80h,3,00h,4,80h,5,00h,6,80h,7,00h,8,80h ;显示缓冲区,8个显示器,16个字节(第一字节内容,第二字节属性),
LED DB 3FH,06H,5BH,4FH,66H,6DH,7DH,27H,7FH,6FH,77H,7CH,39H,5EH,79H,71H ;字形表 0 ~ f:显示 0~F
DB 00h,63h,5ch ;字形表 10:暗,11:上午,12:下午
DB 73H ;P:13H,
CODE ENDS
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -