奇怪是把下面in al,60h改成int 16h 显示倒是正常(这是王爽实验17-2内容中的一个子程序,所以只能用in al,60h而不能用能让程序停下来等待用户输入的int 16h功能)
assume cs:code
code segment
main:
in al,60h ;读取键盘端口
cmp al,1h ;esc键?
je clockexit ;是退出,返回主莱单
cmp al,03bh ;F1?
je F1
cmp al,03ch ;F2?
je F2
jmp clockcon
F1:
mov dx,0 ;改前景
call color
jmp clockcon
F2:
mov dx,1 ;改背景
call color
clockcon:
jmp main
clockexit:
mov ax,4c00h
int 21h
color: ;改前,背景色(颜色值0~7),dx表示调用功能号 dx=0为前景色,dx=1为背景色
push es
push di
push cx
push dx
push ax
push bx
jmp colorstart
colorda db 0,0 ;colorda[0]保存前景色值,colorda[1]保存背景色值
colorstart:
mov cx,0b800h
mov es,cx
mov cx,2000
mov di,1
mov ax,0
mov bx,dx
cmp colorda[bx],7 ;用定址表判断颜色值
jnb ab ;大于或等于7,跳转
inc colorda[bx] ;小于7直接加1
mov al,colorda[bx] ;读取要写屏的颜色
jmp write
ab:
mov colorda[bx],0 ;如果颜色值大于或等于7那么重新置0
mov al,colorda[bx] ;读取要写屏的颜色
jmp write
;改变颜色
write:
mov ah,es:[1] ;先读取当前屏幕字符颜色
cmp bx,1 ;判断功能号,如果1改背景,0改前景色
je colback ;为1跳到改背景
;否则改前景
and ah,11111000b ;只把前景颜色删除,保留其它属性(字符可能还有背景颜色和闪烁特效,这些不能册)
jmp colconv
colback: ;背景颜色
and ah,10001111b ;只删掉背景色保留其它属性(字符可能还有前景颜色和闪烁特效,这些不能册)
shl al,1
shl al,1
shl al,1
shl al,1
colconv: ;进入改变字符颜色过程
or al,ah ;确定当前将要写入的字符颜色
coldo:
mov es:[di],al
add di,2
loop coldo
colorexit:
pop bx
pop ax
pop dx
pop cx
pop di
pop es
ret
code ends
end main
------解决方案--------------------
如果只是调用bios中断进行键盘输入处理的话int 9h和int 16h 就够了 9h号是硬件中断只要有键盘输入而中断控制器没有屏蔽它且IF=1的话那么int 9h 就可以正常发生,然后可以通过软中断int指令调用16h号中断处理程序的0号功能即ah=0 int 16h 来从键盘缓冲区读取一个键盘输入 你的目的只是单纯的通过esc和F1 F2来实现程序的过程调用和程序返回那就不要用16h号中断了 直接读60h端口就可以了,至于键盘缓冲区清除的问题每当执行一次int 16h后它都会把已经读了的键自动清除的
键盘缓冲区位置40:001e到40:003e既然中断可以对它进行读写你自然也就可以用指令改变它的内容了你的程序我还是觉得直接读60h端口是最自然的不用考虑键盘缓冲区里面用了int 16h是否在程序执行前有未读出的键盘输入
------解决方案--------------------
只是读 60h 的话,上次的按键码可能还在那端口里,所以连续不停地读,在一个时间内可能都会有读出那个内容;而在 int9h 里的话,只有发生了按键状态改变,才会触发这个中断,这样不会发生重复读取。断码通知,是硬件上触发 int9 的吧,不是程序可以发送的。