📄 boxatime.asm
字号:
.model small
.stack
.data
count dw 1
ocx dw 0;前一刻横坐标
odx dw 0;前一刻坐标
color db 48;当前颜色
ocolor db 48;前一刻颜色
x dw 319
y dw 199
state db 'Statement:',0ah,0dh,' Click Mouse left key to draw,right key to change color,press ESC to exit',0ah,0dh,0ah,0dh,' press any key to star...$'
.code
main proc far;主程序
start:
mov ax,@data
mov ds,ax
lea dx,state;输出说明
mov ah,9
int 21h
mov ah,1
int 21h
;实现显示时间程序常驻内存功能
mov al,1ch;al<=中断类型,中断指令int 1ch:时钟中断每发生一次都要嵌套调用一次中断类型的处理程序
mov ah,35h;取旧中断向量
int 21h
push es;储存旧代码
push bx
push ds
mov dx,offset time;dx<=程序time的地址
mov ax,seg time;ax<=程序time的代码
mov ds,ax;把time的代码传到代码段
mov al,1ch;
mov ah,25h;设置新中断向量
int 21h
pop ds;恢复ds
sti
;画框功能
mov ax,13h;置显示方式为320x200 256色
int 10h
mov bp,20;设置框大小为20像素
xor cx,cx;置坐标为(0,0)
xor dx,dx;
call box;调用box在(0,0)以异或方式画一个框,以掩盖第一次调用move函数画下的框
sub x,bp;根据框大小界定坐标范围
sub y,bp;
scan:
in al,60h;从键盘缓冲区读入一个扫描码
cmp al,01
jz exit;如果按了ESC键退出
mov ax,03h;读取鼠标状态
int 33h
call checkp;调用坐标界定函数
noscan:
cmp bx,1
jz drawing;如果点击了左键转到画框
cmp cx,ocx ;
jnz next ;
cmp dx,odx ;
jnz next ;
mov al,color ;
cmp al,ocolor ;
jz next1 ;如果框的状态没转变则跳过move
next:
call move
next1:
cmp bx,2
jnz scan
inc color;如果点击了右键,则改变颜色
jmp scan
drawing:
call box;以覆盖方式画一个框
re:
mov ax,03h
int 33h
call checkp
cmp bx,1
jz re;等待松开左键
xchg cx,ocx
xchg dx,odx
call box ;以异或方式在按下左键前一刻坐标画框,擦除前一刻move留下的框
jmp noscan
exit:
pop dx ;恢复寄存器旧状态
pop ds
mov al,1ch
mov ah,25h;恢复旧向量中断
int 21h
mov ax,4c00h
int 21h
main endp
;画点程序
draw proc near
mov ah,0dh;读取当前坐标颜色
int 10h
mov ah,0ch
xor al,color;异或当前颜色,实现擦除痕迹
cmp bx,1
jnz next_
mov al,color;如果bx=1置画点颜色为当前颜色
next_:
int 10h;画点
ret
draw endp
;画框程序
box proc near
mov ax,0a000h;视频储存器地址
mov es,ax;储存到es
push ax;保存寄存器状态
push bx
push cx
push dx
push bp
mov bh,0
mov di,bp
add bp,cx
line1:
call draw;画框的顶线
add dx,di
call draw;画框的底线
sub dx,di
inc cx
cmp cx,bp
jnz line1
mov bp,di
dec di
dec cx
inc dx
add bp,dx
dec bp
line2:
call draw;画框的右线
sub cx,di
call draw;画框的左线
add cx,di
inc dx
cmp dx,bp
jnz line2
pop bp;恢复寄存器状态
pop dx
pop cx
pop bx
pop ax
ret
box endp
;框随鼠标移动函数
move proc near
xchg cx,ocx ;
xchg dx,odx ;
mov al,color ;取框前一刻状态
xchg al,ocolor ;
mov color,al ;
call box;以异或方式画框,以擦除痕迹
mov cx,ocx ;
mov dx,odx ;恢复框当前状态
mov al,ocolor ;
mov color,al ;
call box;以疑惑方式画框,显示当前框
ret
move endp
;界定坐标函数
checkp proc near
cmp cx,x
jb nextb
mov cx,x;如果横坐标溢出则调整为最大横坐标
nextb:
cmp dx,10
ja nex
mov dx,10
nex:
cmp dx,y
jb return
mov dx,y;如果纵坐标溢出,则调整为最大纵坐标
return:
ret
checkp endp
;在右上角显示系统时间函数
time proc near
push ds
push ax
push cx
push dx
mov ax,@data
mov ds,ax
sti
dec count;每中断一次count减1
jnz exit_;count=0则刷新时间
mov bh,0 ;
mov ah,2h;
mov dh,0 ;
mov dl,72;定位到右上角
int 10h ;
mov ah,2ch;取系统时间
int 21h
mov al,ch
cmp al,24d
jnz next_a
mov al,0
next_a:
cbw
call print;输出小时
mov dl,':'
mov ah,2
int 21h
mov al,cl
cbw
call print;输出分钟
mov dl,':'
mov ah,2
int 21h
mov al,dh
cmp al,60d
jnz nexta
mov ax,0
nexta:
cbw
call print;输出秒
mov count,9;因为int 1ch每秒约终端18.2次,置count未9(大约半秒),确保能显示每一秒时间
exit_:
cli
pop dx
pop cx
pop ax
pop ds
iret
time endp
;按时间格式转换为10进制输出
print proc near
push ax
push bx
push cx
push dx
mov cx,10
cwd ;ax符号位扩展到dx
div cx;除以10,以转换10进制
push dx
mov dx,ax
mov ah,2
add dl,30h
int 21h;输出高位
pop dx
add dl,30h
int 21h;输出低位
pop dx
pop cx
pop bx
pop ax
ret
print endp
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -