;按键1清屏。
;按键2设置前景色。
;按键3设置背景色。
;按键4向上滚动一行。
;(1)清屏:将显存中当前屏幕中的字符设为空格符;
;(2)设置前景色:设置显存中当前屏幕中处于奇地址的属性字节的第0、1、2位;
;(3)设置背景色:设置显存中当前屏幕中处于击地址的属性字节的第4、5、6位;
;(4)向上滚动一行:依次将第n+1行的内容复制到第n行处;最后一行为空。
assume cs:code,ds:data
data segment
dw 8 dup(0)
code segment
start:
mov ax,data
mov ds,ax ;设ds
mov ax,0
mov es,ax ;设es
mov ax,es:[9*4]
mov ds:[0],ax ;保存int9的ip
mov ax,es:[9*4+2]
mov ds:[2],ax ;保存int9的cs
mov ax,offset INT9
mov es:[9*4],ax ;子程序偏移放在int9的ip中
mov es:[9*4+2],cs ;cs放在int9cs中
;===============================================================================================
;显示A~Z26个字符
mov ax,0b800h
mov es,ax ;重设es
mov di,160*12+40*2 ;设di
mov al,'A'
s2: mov es:[di],al ;屏幕显示
call short sleep ;延时
inc al ;al+1
cmp al,'Z'
jna s2 ;不大于'Z'进循环
mov ax,4c00h
int 21h
;============================================================================
;延时
sleep: push ax ;延时
push dx
mov ax,0
mov dx,01f00h
s1: sub ax,1
sbb dx,0
cmp ax,0
jne s1
cmp dx,0
jne s1
pop dx
pop ax
ret
;==========================================================================
;新的int9中断
INT9:
push ax ;保存ax
pushf ;标志寄存器压栈
pushf
pop ax
and ah,11111100b ;TF=0,IF=0
call dword ptr ds:[0] ;调用原9号中断
in al,60h ;读60h端口内容
cmp al,02h ;和1的扫描码对比
je PASS1 ;一样就跳
cmp al,03h ;和2的扫描码对比
je PASS2 ;一样就跳
cmp al,04h ;和3的扫描码对比
je PASS3 ;一样就跳
cmp al,05h ;和4的扫描码对比
je PASS4 ;一样就跳
pop ax
iret ;没有一样的退出the9
PASS4: jmp near ptr mypass4
;=======================================================================================
;清屏
PASS1: push si
push es
push cx
push ax
mov ax,0b800h
mov es,ax ;设es
mov cx,2000 ;设cx
mov si,0 ;设si
sub1: mov es:[si],byte ptr ' ' ;
add si,2
loop sub1 ;全屏设' '
pop ax
pop cx
pop es
pop si
pop ax
iret
;======================================================================
;设前景色
PASS2: push si
push es
push cx
push ax
mov ax,0b800h
mov es,ax ;设es
mov si,1 ;设si
mov cx,2000 ;设cx
mov bl,es:[si] ;用bl保存当然颜色参数
and bl,00000111b ;把前景色提出来
cmp bl,7 ;于7比
jb ss2 ;小于跳转
sub bl,bl ;大于或等于清零
ss2: inc bl ;加1
sub2: and byte ptr es:[si],11111000b ;把前景清零
or es:[si],bl ;前景用bl
add si,2 ;下一个颜色位置
loop sub2
pop ax
pop cx
pop es
pop si
pop ax
iret
;====================================================================================
;设背景色
PASS3: push ax
push si
push es
push cx
mov ax,0b800h
mov es,ax ;设es
mov si,1 ;设si
mov bh,es:[si] ;用bh做背景色
shr bh,1
shr bh,1
shr bh,1
shr bh,1 ;右移4位
cmp bh,7 ;于7比
jb ss3 ;小于跳 ;
sub bh,bh ;不小于清零
ss3: inc bh ;加1变色
mov cx,2000 ;2000个颜色位置
sub3: add byte ptr es:[si],10001111b ;背景色清零
shl bh,1
shl bh,1
shl bh,1
shl bh,1 ;bh左移4位
or byte ptr es:[si],bh ;用bh做背景色
add si,2 ;下一个颜色位置
loop sub3
pop cx
pop es
pop si
pop ax
pop ax
iret
;========================================================================================
;向上滚动一行
mypass4: push ax
push si
push di
push es
push ds
push cx
mov ax,0b800h
mov es,ax ;设es
mov ds,ax ;设ds
mov di,0 ;设di
mov si,160 ;设si
cld ;DF零0,正方向
int4: mov cx,160 ;设cx
rep movsb ;ds:si到es:di
cmp si,160*25 ;
ja out1 ;到最后一行下面就退出
jmp short int4
out1:
pop cx
pop ds
pop es
pop di
pop si
pop ax
pop ax
iret
code ends
end start
- [fancx] ========== 其它位不确定就先不管,那么这个数就是???? 00?? 01?? ?1?1, 10/31 09:44
- [游客] 博主的程序很有意思,学习了。 07/13 18:46
- [martian] 博主的主程序执行效果是在屏幕上延时显示26个字母,而非P289的实验16的要求,虽然实现了相应的子程 04/14 15:32
- [hihi] 不错,我第15章刚结束,复习一下! 04/14 15:32
- [jhszcn] 嘎嘎 04/14 14:25
- [wdm] 答案4,中断服务分内中断和外中断,在程序中用定址表有时不用段间跳转,可能没有保存段地址,不一定可以用 04/14 11:51
- [younggay] 对博主的分析没有异议。 04/14 11:40
- [younggay] 理解的不错啊。 我觉得挺正确。 04/14 10:48
- [jhszcn] 谢谢指正 04/13 22:05
- [jhszcn] To younggay: pushf call dword ptr后 04/10 17:54
- [w0922] 你好 !能不能到我的博客看哈 有个问题想请教哈你··· 就是我博客实验十分析的那个问题 04/18 15:19
- [jhszcn] 嘎嘎,谢谢大哥:) 03/27 19:38
- [wdm] 博主终于开通了。呵呵,这里的功能让你更好的穿梭与汇编网的各个版块,还能及时了解很多动态信息和自己论坛 03/26 09:54