写了个程序,动态显示数字时钟,本来要求程序开始等待击键活动才显示时钟。而后击空格键返回DOS。可是我的程序一运行就显示出了时钟,并没有循环检测是否有击键。而且一运行就停不下来。改来改去总不对,烦死了,帮忙看下。
- Assembly code
assume cs:codecode segmenttime db 'hh:mm:ss',13,10,'$'string db 'press any key to continue...',13,10,'$'cmos db 4,2,0start: ;装入代码段的段地址 mov ax,cs mov ds,ax mov dx,offset string ;取得字符串的偏移地址 mov ah,9 int 21H ;调用DOS显示字符串check: ;读取键盘的输入状态 mov dl,0ffH mov al,06H mov ah,0cH int 21H inc al ;如键盘有击键,al为OFFH。否则为00H loopnz checkagain: ;寄存器初始化 mov bx,0 mov si,0 mov cx,3second: push cx mov al,cmos[bx] out 70h,al ;将al送入地址端口70h in al,71h ;从数据端口71h处读出单元内容 mov ah,al mov cl,4 shr al,cl ;右移4位 and ah,0fh ;al分成两个表示BCD码值的数据 add ax,3030h ;BCD码+30h=10进制数对应的ASCII码 mov cs:[si],ax ;ASCII码写入time段 inc bx add si,3 ;si加上3,指向当前位置的后面第三个位置 pop cx loop second;名称:BIOS中断(int 10h);功能:(ah)=2置光标到屏幕指定位置、(ah)=9在光标位置显示字符;参数:(al)=字符、(bh)=页数、(dh)=行号、(dl)=例号; (bl)=颜色属性、(cx)=字符重复个数 mov ah,2 ;置光标 mov bh,0 ;第0页 mov dh,20 ;dh中放行号 mov dl,30 ;dl中放例号 int 10h;名称:DOS中断(int 21h);功能:(ah)=9显示用'$'结束的字符串、(ah)=4ch程序返回;参数:ds:dx指向字符串、(al)=返回值 mov dx,0 mov ah,9 int 21h ;调用0C功能清空键盘缓冲区并调用06号键盘功能 mov dl,0ffH mov ah,0cH mov al,06H int 21H cmp al,0 ;判断是否有字符可读,如没有则al为0 je again ;没有字符可取,跳转到程序的开始 cmp al,0EH ;如果有击键活动,则获取击键的扫描码,如果输入为空格则程序结束 je exit jmp again ;如果输入的不是空格键,则无条件跳转到开始;结束exit: mov ax,4c00h int 21hcode endsend start
------解决方案--------------------------------------------------------
- Assembly code
assume cs:codecode segmenttime db 'hh:mm:ss',13,10,'$'string db 'press any key to continue...',13,10,'$'cmos db 4,2,0start: ;装入代码段的段地址 mov ax,cs mov ds,ax mov dx,offset string ;取得字符串的偏移地址 mov ah,9 int 21H ;调用DOS显示字符串check: ;读取键盘的输入状态 mov dl,0ffH mov al,06H mov ah,06H ;** 0ch -> 06h 0ch 功能会清输入缓冲区的,所以很难等到按键然后继续 int 21H ; test al, al ;** 06h 功能返回时会设置 ZF 状态的,所以可直接使用 loopz checkagain: ;寄存器初始化 mov bx,0 mov si,0 mov cx,3second: push cx mov al,cmos[bx] out 70h,al ;将al送入地址端口70h in al,71h ;从数据端口71h处读出单元内容 mov ah,al mov cl,4 shr al,cl ;右移4位 and ah,0fh ;al分成两个表示BCD码值的数据 add ax,3030h ;BCD码+30h=10进制数对应的ASCII码 mov cs:[si],ax ;ASCII码写入time段 inc bx add si,3 ;si加上3,指向当前位置的后面第三个位置 pop cx loop second;名称:BIOS中断(int 10h);功能:(ah)=2置光标到屏幕指定位置、(ah)=9在光标位置显示字符;参数:(al)=字符、(bh)=页数、(dh)=行号、(dl)=例号; (bl)=颜色属性、(cx)=字符重复个数 mov ah,2 ;置光标 mov bh,0 ;第0页 mov dh,20 ;dh中放行号 mov dl,30 ;dl中放例号 int 10h;名称:DOS中断(int 21h);功能:(ah)=9显示用'$'结束的字符串、(ah)=4ch程序返回;参数:ds:dx指向字符串、(al)=返回值 mov dx,0 mov ah,9 int 21h ;调用0C功能清空键盘缓冲区并调用06号键盘功能 mov dl,0ffH mov ah,06H ;** 0ch -> 06h 0ch 功能调用会清输入缓冲区,所以应使用 06h mov al,06H int 21H cmp al,0 ;判断是否有字符可读,如没有则al为0 ;** 这两条指令多余 je again ;没有字符可取,跳转到程序的开始 cmp al,20H ;** 如果是空格,应该为 20h。0eh 是 Ctr+N! je exit jmp again ;如果输入的不是空格键,则无条件跳转到开始;结束exit: mov ax,4c00h int 21hcode endsend start