dl里存的是ASCII字符,每次加1,如果溢出了(jo跳转)就(不继续了)跳转到OVER语句块,否则就用int 21H中断调用dos输出它(默认输出的就是dl)。而要输出空格时,因为要保存当前dl的内容,就要把它入栈,因为PUSH和POP只能对16位寄存器操作,所以干脆对dx(低8位是dl,高8位时dh)入栈出栈。另外dh用来保存了计数值,每次输出完ASCII字符和空格后就把它减1,如果减少到0了(jz跳转)就进入C_xun语句块输出回车和换行(注意是两个东西)。还要注意程序开头要有mov ah,02H设置显示方式,结尾必须要有mov ax,4c00H和int 21H。
prognam segment
main proc far
assume cs:prognam
start:
mov ah, 02H ;设置显示方式
mov dl,20H ;从20H开始(加1后的21H是感叹号)
mov dh,10H ;用来计数(16个换行一次)
B_xun:
inc dl ;dl+1
jo OVER ;溢出则跳转
int 21H ;调用dos输出
push dx ;push/pop只能对字操作,所以把(DX)=(DH,DL)入栈
mov dl,20H ;空格=21H
int 21H
pop dx ;出栈还给dx
dec dh ;将计数值减1
jz C_xun ;等于0则跳转
jnz B_xun
C_xun:
push dx ;入栈保存dx(其实是要保存dl)
mov dl,0AH ;回车符=0AH
int 21H
mov dl,0DH ;换行符=0DH
int 21H
pop dx ;因为要拿回dl时会改变dh,所以先做
mov dh,10H ;重置dh以重新开始计数
jmp B_xun ;回到输出ascii表的循环
OVER:
mov ax, 4c00H ;必须要有的
int 21H
main endp
prognam ends
end
这次bl用来保存每一行应该有多少字符,dh用来实际地对这个值每次减少1然后输出字符,一旦减少到0就(jz跳转)进入C_xun语句块,输出回车换行后,对bl+1也就是下一行要比上一行多一个字符,并紧接着又对这个值进行检测,一旦它是16就跳入CHO_ZHI语句块赋值回1,表示最大就是一行输出15个,然后就又回到1了。然后把bl的值给dh,因为实际还是在dh上作减法而不能随便去改bl(影响计数)。
prognam segment
main proc far
assume cs:prognam
start:
mov ah, 02H ;设置显示方式
mov dl,20H ;从20H开始(加1后的21H是感叹号)
mov bl,01H ;用来控制循环次数
mov dh,bl ;用来计数(从1开始)
B_xun:
inc dl ;dl+1
jo OVER ;溢出则跳转
int 21H ;调用dos输出
push dx ;push/pop只能对字操作,所以把(DX)=(DH,DL)入栈
mov dl,20H ;空格=21H
int 21H
pop dx ;出栈还给dx
dec dh ;将计数值减1
jz C_xun ;等于0则跳转
jnz B_xun
C_xun:
push dx ;入栈保存dx(其实是要保存dl)
mov dl,0AH ;回车符=0AH
int 21H
mov dl,0DH ;换行符=0DH
int 21H
pop dx ;因为要拿回dl时会改变dh,所以先做
inc bl ;bl+1
push bx ;存一下
sub bl,10H ;减16试一下
jz CHO_ZHI ;减16为0则跳转
pop bx ;没跳转就拿出来
mov dh,bl
jmp B_xun ;回到输出ascii表的循环
CHO_ZHI:
pop bx ;拿出bl,栈里的bl没什么用了
mov bl,01H ;重新给个1
mov dh,bl
jmp B_xun
OVER:
mov ax, 4c00H ;必须要有的
int 21H
main endp
prognam ends
end
如把溢出跳转那句去掉,就能不停地输出了。