首页 理论教育 程序设计实例

程序设计实例

时间:2022-02-28 理论教育 版权反馈
【摘要】:将字符串原地反序排列后,以字符串的方式输出,源程序如下。显然这是一个二重循环程序,内循环次数为8,完成对一字节数据中“1”的个数的统计;外循环次数为128,完成对128个字节的数据统计处理。程序如下: 编制判断两个字符串长均为COUNT的字符串STRING 1,STRING 2是否相同的程序段。由上述分析,此问题关键是进行5次除法操作,故可采用计数循环方式设计。

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

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈