4.6 程序设计实例
【例4-17】 从键盘读入一个字符串(长度小于80),然后将字符串以与输入相反的顺序显示出来。
方法一 采用INT 21H的10号功能读入字符串,输入缓冲区的第2个字节是由系统置入的实际字符个数。将字符串原地反序排列后,以字符串的方式输出,源程序如下。
DATA SEGMENT
BUF DB 80,?,80DUP(?) ;按10号调用方式设置缓冲区
LF DB 0AH
DATA ENDS
CODE SEGMENTASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS,AX
LEA DX,BUF
MOV AH,0AH
INT 21H
MOV DL,LF
MOV AH,02H
INT 21H
MOV BL,BUF+1
XORBH,BH
MOV BUF[BX+2],‘$’ ;置入/输出字符串的结束标志
DEC BX
MOV SI,0
LP:CMP SI,BX
JG E OUTP
MOV AL,BUF[SI+2]
XCHG AL,BUF[BX+2]
MOV BUF[SI+2],AL
INC SI
DEC BX
JMP LP
OUTP:LEA DX,BUF+2 ;调9号显示字符串
MOV AH,09H
INT 21H
MOV AH,4CH;返回DOS
INT 21H
CODE ENDS
END START
方法二 不设输入缓冲区,以字符方式读入。每输入一个字符,将其进栈,直到遇到回车结束,然后,依次出栈、输出。源程序如下。
STACK SEGMENT STACK
DB 128DUP(?)
STACK ENDS
DATA SEGMENT
CRDB 0DH
LF DB 0AH
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,SS:STACK,DS:DATA
START:MOV AX,DATA
MOV DS,AX
XORCX,CX ;CX=0
INP:MOV AH,01H
INT 21H ;调1号输入一个字符
CMP AL,CR;字符与回车比较
JE DONE;相等,则转向输出
PUSH AX;不相等,则入栈
INC CX;计数器加1
JMP INP
DONE:JCXZ EXIT
MOV DL,LF;输出换行字符
MOV AH,02H
INT 21H
OUTP:POP DX;出栈
MOV AH,02H;调2号中断显示
INT 21H
LOOP OUTP;判断是否继续循环
EXIT:MOV AH,4CH;返回DOS
INT 21H
CODE ENDS
END START
【例4-18】 从以BUF单元开始存放有128字节的数据块,编一程序,统计该数据块中所有位为“1”的个数。
分析 我们知道,一个字节数据中含有8位二进制数。我们需先取一字节数据,将其左移或右移,判断进位标志CF,当CF=1时就计数。完成8次循环后,该一字节数据才处理完,然后再取下一数据重复8次循环移位,判断计数,直到128个字节数据都处理完。显然这是一个二重循环程序,内循环次数为8,完成对一字节数据中“1”的个数的统计;外循环次数为128,完成对128个字节的数据统计处理。程序如下:
DATA SEGMENT
BUF DB 15H,36H,18H,03H,0FFH,…,7FH
;共128个数据
COUNT DW ?
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS,AX
MOV SI,OFFSET BUF
MOV CX,128;CX←外层循环次数256
XORBX,BX;存放结果寄存器BX清0
LP0:MOV DH,8;DH←内层循环计数次数8
MOV AL,[SI];取一数据送AL
LP1:RORAL,1;AL循环右移一位
JNC NEXT;若对应位不为“1”,转NEXT
INC BX;若对应位为“1”,则BX←BX+1
NEXT:DEC DH;内循环计数控制
JNZ LP1;若一字节没处理完则继续
INC SI;修改取数地址
LOOP LP0;外循环计数控制,128个字节没
;处理完则继续
MOV COUNT,BX;128个字节处理完,则保存“1”
;的个数计数结果
MOV AH,4CH;返回DOS
INT 21H
CODE ENDS
END START
【例4-19】 编制判断两个字符串长均为COUNT的字符串STRING 1,STRING 2是否相同的程序段。若相同,则显示“MATCH!”,否则就显示“NO MATCH!”
方法一 采用串指令方法,这是一种固定比较方法,原串地址为:DS:SI,目的串地址为:ES:DI,串的大小为CX。
DATA SEGMENT
STRING 1 DB ′ABCD′
STRING 2 DB ′ABCD′
COUNT=STRING 2-STRING 1 ;计算字符串的个数
BUF DB ′MATCH!$′
BUF1 DB ′NO MATCH!$′
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,ES:DATA
START:MOV AX,DATA
MOV DS,AX
MOV ES,AX
LEA SI,STRING 1;设置原串
LEA DI,STRING 2;设置目的串
MOV CX,COUNT
CLD
REPE CMPSB;比较两串
JNZ LP;两串不相等,则转移到LP
LEA DX,BUF;显示“MATCH!”
MOV AH,09H
INT 21H
JMP EXIT;退出程序
LP:LEA DX,BUF1;显示“NO MATCH!”
MOV AH,09H
INT 21H
EXIT:MOV AH,4CH;返回DOS
INT 21H
CODE ENDS
END START
方法二 采用逐一比较两串中字符是否相等,来判断两串是否相等。
DATA SEGMENT
STRING 1 DB ′ABCD′
STRING 2 DB ′ABCD′
COUNT=STRING 2-STRING 1 ;计算字符串的个数
BUF DB′MATCH!$′
BUF1DB′NO MATCH!$′
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS,AX
LEA SI,STRING 1;设置原串
LEA DI,STRING 2;设置目的串
MOV CX,COUNT
LP:MOV AH,[SI]
CMP AH,[DI];一个一个字符比较
JNZ LP1;不相等,则转移到LP1
INC SI
INC DI;改变地址
DEC CX
JNZ LP;判断是否比较完
LEA DX,BUF;显示“MATCH!”
MOV AH,09H
INT 21H
JMP EXIT;退出程序
LP1:LEA DX,BUF1;显示“NO MATCH!”
MOV AH,09H
INT 21H
EXIT:MOV AH,4CH;返回DOS
INT 21H
CODE ENDS
END START
【例4-20】 编写一个16位的二进制数转换成十进制数,并将十进制数的ASCII码存入存储器字节单元中。
分析 任何一个二进制数要转换为一个十进制数,采用的方法是多少位二进制数表示的最大十进制数整除,用商表示十进制数字的位数。例如本题是一个16位的二进制数能表示最大的十进制数字有五位,即最高位是“万位”。因此,转换的方法是:用二进制除以104得到的整数商是十进制数的“万”位,用余数再除以103得到的整数商是十进制数的“千”位,这样依次做下去,可以得到十进制数的“百”位、“十”位、“个”位。这些商的十进制数是用BCD码表示的。要转换成ASCII码,只要加上30H即可。然后用2号DOS功能调用进行输出显示。由上述分析,此问题关键是进行5次除法操作,故可采用计数循环方式设计。程序为:
DATA SEGMENT
COUT DW 10000,1000,100,10,1
BINARY DW 0ABEH
BUF DB 6 DUP(?)
DATA ENDS
STACK SEGMENT
DB 256 DUP (?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
START:MOV AX,DATA
MOV DS,AX
MOV AX,STACK
MOV SS,AX
MOV AX,BINARY;十六位二进制数
MOV CX,5
MOV BX,OFFSET CONT;整除数
LP:CWD
DIV WORD PTR[BX]
ADD AL,30H;商转成ASCII码
MOV BUF[SI],AL;将万位放入BUF存储区
INC SI
MOV AX,DX;余数送入AX
ADD BX,2;整除数
LOOP LP;判断整除是否结束
MOV BUF[SI],′$′;数据串结尾加“$”
LEA DX,BUF
MOV AH,9;调9号显示字符串
INT 21H
MOV AH,4CH;返回DOS
INT 21H
CODE ENDSEND START
【例4-21】 编写将用ASCII码表示的五位十进制数(不大于65535)转换成二进制数的程序。
分析 设从键盘输入接收十进制数字符的ASCII字符,首先将其转换成十进制数字(BCD),然后再采用累加和乘10加系数的方法变成二进制数,如果被转换数所对应的BCD码为X4X3X2X1X0,则有计算公式:
X4X3X2X1X0=X4×104+X3×103+X2×102+X1×10+X0
=((((X4×10)+X3)×10+X2)×10+X1)×10+X0
其运算结果就是二进制数了。
程序为:
DATA SEGMENTBUF DB 32145
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS,AX
LEA BX,BUF
MOV SI,10
MOV CX,5
SUB AX,AX;AX清0
LP:MULSI;AX×10
MOV DL,[BX];取五位十进制数的高位
MOV DH,0
SUB DL,30H;将ASCII码变成二进制数
ADD AX,DX
INC BX
LOOP LP;判断五位是否完成
MOV AH,4CH;返回DOS
INT 21H
CODE ENDS
END START
【例4-22】 将BX的值以十六进制形式显示。
分析 由于一个十六进制位对应4个二进制位,因此,要以十六进制形式显示一个16位数,可以利用循环结构,从左到右每4个二进制位一组,依次求得其对应的十六进制位。每次循环显示一个十六进制位,循环次数已知,是4次。显示一个十六进制位前,必须首先将其对应的4个二进制位移到最低位,再转换为ASCII码。由于数字0~9的ASCII码为30H~39H,字母A~F的ASCII码为41H~46H,所以在转换为ASCII码时,若十六进制位的值为0~9,则加30H,否则,加37H,程序如下:
CODE SEGMENT
ASSUME CS:CODE
START:MOV BX,1234H ;欲显示的值送BX
MOV CL,4;设置循环次数
LP::ROLBX,CL;BX最高4位循环到低4位
MOV DL,BL;BL的值保存在DL中
AND DL,0FH;屏蔽高4位
CMP DL,′A′;DL的值与A值比较
JLDISP;小于,则DL加30H
ADD DL,07H;大于,则DL加37H
DISP:ADD DL,30H
MOV AH,02H;调2号显示字符
INT 21H
LOOP LP;4位是否显示完
MOV AH,4CH;返回DOS
INT 21H
CODE ENDS
END START
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。