一 问题描述及要求
在屏幕上开出三个窗口:
用“<-”和“->”键选择左窗口或右窗口为当前活动窗口,从键盘输入字符, 字符就会从当前活动窗口的最下行开始显示,同时也在下窗口显示。当一行字符显示满后(左右窗口一行显示20个字符,下窗口显示50个字符),窗口自动向上卷动一行,输入的字符仍显示于最低一行,窗口最高一行向上卷动后消失,按ESC键程序运行结束
二 设计思想论述
程序启动时初始化三个窗口,窗口的属性用一个变量property保存起来,方便改变窗口的属性。属性为一个字节的变量,变量每位的意义如下:
7 | 6 | 5 | 4 |
| 2 | 1 | 0 |
闪烁(7) 背景(**) 亮度(3) 前景(2-0)
0=正常显示 0=正常显示
1=闪烁显示 1=加强亮度
初始化窗口后接受用户的输入,根据用户输入的字符执行相应的操作,用户输入ESC时退出程序,输入<-切换到左窗口,输入->切换到右窗口,输入Backspace在活动窗口和底部窗口删除一个字符,输入Enter在活动窗口和底部窗口中换行,输入一个字符时在活动窗口和底部窗口显示,显示满一行时自动向上卷动一行。
三 程序清单
- ;--------------------------------------------------------
- ;在屏幕上开出三个窗口
- ;--------------------------------------------------------
- ;********************************************************
- data segment
- property db 01100101B ;字符的属性
- lminrow db 5 ;左窗口最小行号
- lmaxrow db 14 ;左窗口最大行号
- lmincol db 10 ;左窗口最小列号
- lmaxcol db 29 ;左窗口最大列号
- rminrow db 5
- rmaxrow db 14
- rmincol db 50
- rmaxcol db 69
- bminrow db 18 ;底部窗口最小行号
- bmaxrow db 21
- bmincol db 15
- bmaxcol db 64
- lrow db 14 ;左窗口阻塞时行坐标
- lcol db 10 ;左窗口阻塞时列坐标
- rrow db 14 ;右窗口阻塞时行坐标
- rcol db 50 ;右窗口阻塞时列坐标
- activewin db 1 ;当前活动窗口(1=左窗口,2=右窗口)
- data ends
- ;********************************************************
- code segment
- ;--------------------------------------------------------
- ;主程序
- main proc far
- assume cs:code,ds:data
- start:
- push ds
- xor ax,ax
- push ax
- mov ax,data
- mov ds,ax
- mov ax,0B800h
- mov es,ax
- call init
- call input
- call cls
- mainret:
- ret
- main endp
- ;--------------------------------------------------------
- ;程序初始化
- init proc near
- push ax
- push bx
- push cx
- push dx
- mov bh,property
- mov al,0
- ;初始化左窗口
- mov ch,lminrow
- mov cl,lmincol
- mov dh,lmaxrow
- mov dl,lmaxcol
- mov bh,property
- mov ah,6
- int 10h
- ;初始化右窗口
- mov ch,rminrow
- mov cl,rmincol
- mov dh,rmaxrow
- mov dl,rmaxcol
- mov ah,6
- int 10h
- ;初始化底部窗口
- mov ch,bminrow
- mov cl,bmincol
- mov dh,bmaxrow
- mov dl,bmaxcol
- mov ah,6
- int 10h
- ;将光标置于左窗口底部开始处
- mov bh,0
- mov dh,lmaxrow
- mov dl,lmincol
- mov ah,2
- int 10h
- initret:
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- init endp
- ;--------------------------------------------------------
- ;循环输入字符,在活动窗口和底部窗口显示
- input proc near
- push ax
- push bx
- push cx
- push dx
- push di
- ;将di设置到底部窗口最下行开始
- mov ax,0
- mov bx,0
- mov al,bmaxrow
- mov bl,80
- mul bl
- mov bl,bmincol
- add ax,bx
- shl ax,1
- mov di,ax
- ;循环输入
- mov ax,0
- mov bx,0
- mov cx,0
- inputlop1:
- mov ah,0
- int 16h
- ;判断是否是ESC
- cmp ah,01
- je inputret ;是ESC则退出
- ;判断是否是<-
- cmp ah,4bh
- je toleftwin
- ;判断是否是->
- cmp ah,4dh
- je torightwin
- ;判断是否是Backspace
- cmp ah,0eh
- je backspace
- ;判断是否是
- cmp ah,1ch
- je enter
- ;输出字符
- mov bh,0
- mov bl,property
- mov ah,0eh
- int 10h
- mov byte ptr es:[di],al
- inc cx
- add di,2
- call actscroll
- call botscroll
- jmp inputlop1
- toleftwin:
- mov bl,activewin
- cmp bl,1
- je inputlop1 ;当前活动窗口已是左窗口
- mov dh,lrow
- mov dl,lcol
- call switchwin
- jmp inputlop1
- torightwin:
- mov bl,activewin
- cmp bl,2
- je inputlop1 ;当前活动窗口已是右窗口
- mov dh,rrow
- mov dl,rcol
- call switchwin
- jmp inputlop1
- backspace:
- call deletech
- jmp inputlop1
- enter:
- call crlf
- jmp inputlop1
- inputret:
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- input endp
- ;--------------------------------------------------------
- ;转换窗口
- ;参数:
- ;* dh/dl=新窗口的行/列
- switchwin proc near
- push ax
- push bx
- push cx
- ;保存当前活动窗口光标的坐标
- push dx
- mov ah,3
- mov bh,0
- int 10h
- mov cl,activewin
- cmp cl,1
- je lactive
- jmp ractive
- lactive:
- mov lrow,dh
- mov lcol,dl
- mov activewin,2 ;新窗口为右窗口
- jmp switch
- ractive:
- mov rrow,dh
- mov rcol,dl
- mov activewin,1 ;新窗口为左窗口
- ;切换窗口
- switch:
- ;置光标
- pop dx
- mov ah,2
- mov bh,0
- int 10h
- switchwinret:
- pop cx
- pop bx
- pop ax
- ret
- switchwin endp
- ;--------------------------------------------------------
- ;判断活动窗口是否需要向上滚屏,如果需要则滚屏
- actscroll proc near
- push ax
- push bx
- push cx
- push dx
- ;获取当前光标位置
- mov ah,3
- mov bh,0
- int 10h
- mov bl,activewin
- cmp bl,1
- je islactive
- jmp isractive
- islactive: ;当前活动窗口为左窗口
- cmp dl,lmaxcol
- ja lscroll
- jmp actscrollret
- isractive: ;当前活动窗口为右窗口
- cmp dl,rmaxcol
- jbe actscrollret
- rscroll: ;右窗口上卷
- mov al,1
- mov bh,property
- mov ch,rminrow
- mov cl,rmincol
- mov dh,rmaxrow
- mov dl,rmaxcol
- mov ah,6
- int 10h
- ;置光标
- mov bh,0
- mov dh,rmaxrow
- mov dl,rmincol
- mov ah,2
- int 10h
- jmp actscrollret
- lscroll: ;左窗口上卷
- mov al,1
- mov bh,property
- mov ch,lminrow
- mov cl,lmincol
- mov dh,lmaxrow
- mov dl,lmaxcol
- mov ah,6
- int 10h
- ;置光标
- mov bh,0
- mov dh,lmaxrow
- mov dl,lmincol
- mov ah,2
- int 10h
- actscrollret:
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- actscroll endp
- ;--------------------------------------------------------
- ;判断底部窗口是否需要滚动,如需要则滚动底部窗口
- ;参数:
- ;* cx=最后一行的字符数
- ;* di=指向下一字符的指针
- botscroll proc near
- push ax
- push bx
- push dx
- mov ax,0
- mov bx,0
- ;计算底部窗口每行能容纳的字符数
- mov al,bmaxcol
- mov bl,bmincol
- sub al,bl
- inc al
- cmp cx,ax
- jb botscrollret
- bscroll: ;底部窗口滚动
- mov al,1
- mov bh,property
- mov ch,bminrow
- mov cl,bmincol
- mov dh,bmaxrow
- mov dl,bmaxcol
- mov ah,6
- int 10h
- mov cx,0 ;cx清零
- ;将di设置到底部窗口最下行开始
- mov ax,0
- mov bx,0
- mov al,bmaxrow
- mov bl,80
- mul bl
- mov bl,bmincol
- add ax,bx
- shl ax,1
- mov di,ax
- botscrollret:
- pop dx
- pop bx
- pop ax
- ret
- botscroll endp
- ;--------------------------------------------------------
- ;删除一个字符
- deletech proc near
- push ax
- push bx
- push dx
- push cx
- ;取得光标位置
- mov ah,3
- mov bh,0
- int 10h
- ;判断活动窗口
- mov al,activewin
- cmp al,1
- je isleft
- isright:
- cmp dl,rmincol
- jne delch
- delr: ;屏幕下卷,并删除一个字符
- mov al,1
- mov bh,property
- mov ch,rminrow
- mov cl,rmincol
- mov dh,rmaxrow
- mov dl,rmaxcol
- mov ah,7
- int 10h
- ;置光标
- mov bh,0
- mov ah,2
- int 10h
- ;删除字符
- mov al,0
- mov cx,1
- mov ah,0ah
- int 10h
- jmp delb
- isleft:
- cmp dl,lmincol
- jne delch
- dell:
- mov al,1
- mov bh,property
- mov ch,lminrow
- mov cl,lmincol
- mov dh,lmaxrow
- mov dl,lmaxcol
- mov ah,7
- int 10h
- ;置光标
- mov bh,0
- mov ah,2
- int 10h
- ;删除字符
- mov al,0
- mov cx,1
- mov ah,0ah
- int 10h
- jmp delb
- delch:
- dec dl
- mov ah,2
- int 10h
- mov bh,0
- mov al,0
- mov cx,1
- mov ah,0ah
- int 10h
- delb:
- pop cx
- cmp cx,0
- je delbch
- sub di,2
- mov byte ptr es:[di],0
- dec cx
- jmp deletechret
- delbch:
- ;窗口下移
- mov al,1
- mov bh,property
- mov ch,bminrow
- mov cl,bmincol
- mov dh,bmaxrow
- mov dl,bmaxcol
- mov ah,7
- int 10h
- ;改变di和cx
- mov ax,0
- mov al,bmaxcol
- sub al,bmincol
- mov cx,ax
- shl ax,1
- add di,ax
- ;删除字符
- mov byte ptr es:[di],0
- deletechret:
- pop dx
- pop bx
- pop ax
- ret
- deletech endp
- ;--------------------------------------------------------
- ;当前活动窗口和底部窗口回车换行
- crlf proc near
- push ax
- push bx
- push dx
- push cx
- ;底部窗口回车换行
- ;向上卷动
- mov al,1
- mov bh,property
- mov ch,bminrow
- mov cl,bmincol
- mov dh,bmaxrow
- mov dl,bmaxcol
- mov ah,6
- int 10h
- pop cx
- ;重置di和cx
- shl cx,1
- sub di,cx
- ;活动窗口回车换行
- mov bl,activewin
- cmp bl,1
- jne rightact
- leftact:
- ;卷动窗口
- mov al,1
- mov bh,property
- mov ch,lminrow
- mov cl,lmincol
- mov dh,lmaxrow
- mov dl,lmaxcol
- mov ah,6
- int 10h
- ;重置光标
- mov dl,lmincol
- mov bh,0
- mov ah,2
- int 10h
- jmp crlfret
- rightact:
- ;卷动窗口
- mov al,1
- mov bh,property
- mov ch,rminrow
- mov cl,rmincol
- mov dh,rmaxrow
- mov dl,rmaxcol
- mov ah,6
- int 10h
- ;重置光标
- mov dl,rmincol
- mov bh,0
- mov ah,2
- int 10h
- crlfret:
- mov cx,0
- pop dx
- pop bx
- pop ax
- ret
- crlf endp
- ;--------------------------------------------------------
- ;清屏
- cls proc near
- push ax
- push bx
- push cx
- push dx
- mov al,0
- mov bh,0
- mov ch,0
- mov cl,0
- mov dh,24
- mov dl,79
- mov ah,6
- int 10h
- clsret:
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- cls endp
- ;--------------------------------------------------------
- code ends
- ;********************************************************
- end start