data segment
min1db '0'
min2db'0'
mdb ':'
sec1   db'0'
sec2db'0'
m2db':'
msec1db'0'
msec2db'0'
countequ$-min1
hdb0
data ends


code segment
main proc far
assume cs:code,ds:data


start:
movax,data
movds,ax
callclean_screen
calllocate_cursor
callshow


movah,0;键盘中断,
int 16h;入口参数AH=00H——读键盘,出口参数:AH=键盘的扫描码
;AL=字符的ASCII码 
cli;cli是关中断
moval,08h;中断类型8    功能是定时器,I/O口为20~23  
mov    ah,35h ;获取08h号中断的原入口地址(去取中断向量,调用参数al=中断类型,返回参数es:bx=中断向量)
int    21h
push  es
pushbx
 pushds;SEG就是取段地址,offset 是取偏移地址
movax,seg int 08h;int 8是系统时间中断,计算机的硬件时钟会以固定频率触发8号中断
movds,ax               
mov    dx,offset int08h;设置08h号中断的新入口地址(offset 是取偏移地址)
mov    al,08h
  mov    ah,25h;设置中断向量,(调用参数  ds:dx=中断向量,al=中断类型号)
int    21h                 ;调用08h号中断的服务程序,获取
popds


inal,21h;从21H号端口输入8位数据到AL寄存器
pushax
moval,11111100b
out21h,al;将AL的值写入21H端口
moval,00110110b
out43h,al;将AL的值写入43H端口
movax,11931
out40h,al
moval,ah
out40h,al
sti;cli是打开中断



s1:calllocate_cursor
callshow
movah,0bh;检验键盘状态,al=00有输入,al=ff无输入
int21h
incal;加1指令
jnzs1;不为0时跳转

movah,08h;键盘输入(无回显),al=输入字符
int21h

cmpal,'d'
jed1;ZF= 1的时候{即结果为0},转至标号处执行(CMP :::(DX)=(CX)时,则ZF=1;)
cmpal,'m'
jem1
cmpal,'r'
jer1
jmps1;无条件转移指令



r1:popax;重新计时,初始化程序,跳转到开始start
out21h,al;将AL的值写入21H端口
popdx;把bx送到dx
popbx
pushds
mov ds,bx
mov    al,08h
  mov    ah,25h;设置中断向量,(调用参数ds:dx=中断向量,al=中断类型号)
int    21h   
pop ds
movh,0
movmin1,30h
movmin2,30h
movsec1,30h
movsec2,30h
movmsec1,30h
movmsec2,30h
jmpstart



m1:mov dh,h
mov dl,25
mov bh,0
mov ah,2
int10h
callshow
inch
jmps1



d1:popax
out21h,al


popdx;把bx送到dx
popds;把es送到ds
movax,2508h; 0010 0101 0000 1000
int21h


moval,00110110b
out43h,al
subal,al
out40h,al
out40h,al


movah,4ch
int21h



main        endp




int08h   proc   near 


push ax
pushds
mov ax,data
mov ds,ax
inc msec2
cmp msec2,3ah
jbt;低于(不高于等于)时转移
mov msec2,30h
incmsec1
cmp msec1,3ah
jbt
movmsec1,30h
inc sec2
cmp sec2,3ah
jb t
mov sec2,30h
inc sec1
cmp sec1,36h
jb t
mov sec1,30h
inc min2
cmp min2,3ah
jbt
movmin2,30h

inc min1
cmp min1,36h
jbt
mov min1,30h




t:mov al,20h
out 20h,al
popds
pop ax
iret
                                ;中断返回
int08h   endp                                 ;中断服务程序结束

clean_screen proc near;清屏操作
pushax
pushbx
pushcx
pushdx
movah,6;功能06H功能描述:初始化屏幕或滚屏,这个服务程序的功用是把某一个设定好的矩形区域内的文字向上或向下移动
;入口 参数:AH=06H——向上滚屏,07H——向下滚屏
;AL=滚动行数(0——清窗口),向上移动的列数存入 AL 中 ( 如果 AL 为零,表示使矩形区域的所有列均向上移 )
;BH=空白区域的缺省属性,底端移入空格列的属性存于 BH
;(CH、CL)= 窗口的左上角位置(Y坐标,X坐标),矩形区域是藉由 CX、DX 来设定左上角与右上角的座标
;(DH、DL)=窗口的右下角位置(Y坐标,X坐标)
;出口参数:无
moval,0;,左上角的行与列分别由 CL、CH 设定,右下角的行与列由 DL、DH 设定。
movbh,7
movch,0
movcl,0
movdh,24
movdl,79
int10h
popdx
popcx
popbx
popax
ret
clean_screen endp


locate_cursor proc near;定位光标
pushdx
pushbx
pushax
mov dh,0;此功能是设定光标位置,位置用 DH、DL 表示,DH 表示列号,DL 表示行号
mov dl,0;由左至右称之为『列』,屏幕最上面一列为第零列,紧靠第零列的下一列称为第一列…
mov bh,0;由上而下称之为『行』,屏幕最左边一行称之为第零行,紧靠第零行右边的一行为第一行。
mov ah,2;故最左边,最上面的位置为 DH=0 且 DL=0;最左边第二列,DH=1,DL=0。
int10h;如果是文字模式时,BH 为欲改变光标位置的显示页,如果是图形模式,BH 要设为 0。
popax;在文字模式下,字符的位置类似数学直角座标系的座标,但是 Y 轴方向相反
;Y 轴是以屏幕最上面为零,越下面越大,直到 24 为止,存于 DH 内。X 轴和直角座标系相同,越右边越大,
popbx;存于 DL 内,其最大值视显示模式而变。
popdx
ret
locate_cursor endp


show proc near

pushcx
pushbx
pushsi
pushax
movcx,count
movsi,offsetmin1
movbl,7




show1:
movah,0eh
moval,[si]
int10h
incsi
loopshow1
popax
popsi
popbx
popcx

ret
show endp
code ends
end start

09-06 22:23