二、字符数据处理
在应用程序的设计中,经常会遇到各种字符或字符串的处理。字符处理通常包括字符的比较、检索、插入、删除和统计等。
1.字符串比较
例、在数据区BUF1和BUF2地址开始分别有一字符串,长度均为14字节。试比较这两个字符串,若相同,则给RES单元置0;若不同,则给RES单元置0FFH,并将失配字节地址送RES+1开始的两个存储单元中。
源程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 DATA SEGMENT BUF1 DB 'I am a student' BUF2 DB 'I am a studant' RES DB 3 DUP (?) NUMBER EQU 14 DATA ENDS STACK1 SEGMENT PARA STACK 'STACK' STA DB 100 DUP (?) STACK1 ENDS CODE SEGMENT ASSUME CS: CODE, DS: DATA, ES:DATA, SS: STACK1 START: MOV AX, DATA MOV DS, AX MOV ES, AX LEA BX, RES LEA SI, BUF1 LEA DI, BUF2 MOV CX, NUMBER CLD REPE CMPSB JNZ UNSAME MOV AX, 0 MOV [BX], AL MOV DL, [BX] JMP OVER UNSAME: MOV AX, 0FFH MOV [BX], AL INC BX DEC DI MOV [BX], DI OVER: MOV AH, 4CH INT 21H CODE ENDS END START
2.字符串检索
字符串检索就是在一个字符串中寻找一些关键字符或关键字符(串)。
例、在内存数据区有一数据块,首地址BUF,长度为50字节。检索其中是否有与内存单元KEYWORD中相同的字符。若有则记录第一个遇到的关键字地址;若无则DI赋0。
源程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 DATA SEGMENT KEYWORD DB 50H BUF DB 20H, 34H, 98H, 78H, …… RES DW ? DATA ENDS STACK1 SEGMENT PARA STACK ‘STACK’ STA DB 100 DUP (?) STACK1 ENDS CODE SEGMENT ASSUME CS: CODE, DS: DATA, ES: DATA, SS:STACK1 START: MOV AX, DATA MOV DS, AX MOV ES, AX MOV AL, KEYWORD LEA DI, BUF MOV CX, 50 CLD REPNE SCASB ;重复搜索 JZ FOUND MOV DI, 0 JMP OVER FOUND: DEC DI MOV RES, DI ;送第一个遇到的关键字地址 OVER: MOV AH, 4CH INT 21H CODE ENDS END START
3.字符插入与删除
字符的插入和删除是字符运用的主要形式。
1) 字符插入
例、假设从BUF1地址开始有一个长度为100的字符串,串长度存于LONG单元。现要求在第一个“E”字符后插入一个字符串,其长度6。该字串存于BUF2单元开始的存储区中。若进行插入,SIGN单元置1,否则置0。
源程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 DATA SEGMENT LONG DB 100 BUF1 DB 'ABCDEFGADE……' FREEDOM DB 6 DUP (?) BUF2 DB ‘INSERT’ SIGN DB ? DATA ENDS STACK1 SEGMENT PARA STACK 'STACK' STA DB 100 DUP (?) STACK1 ENDS CODE SEGMENT ASSUME CS: CODE, DS: DATA, ES: DATA, SS: STACK1 START: MOV AX, DATA MOV DS, AX MOV ES, AX MOV CL, LONG LEA DI, BUF1 MOV AL, 'E' CLD REPNE SCASB JZ FOUND MOV SIGN, 0 JMP OVER FOUND: MOV SI, OFFSET FREEDOM-1 MOV DI, OFFSET FREEDOM+5 STD REP MOVSB LEA SI, BUF2+5 MOV CX, 6 STD REP MOVSB MOV SIGN, 1 OVER: MOV AH, 4CH INT 21H CODE ENDS END START
2)字符删除
例、假设从BUF地址开始有一个字符串,串长度存于LONG单元。现要求删除所有的“D”字符并要求修改字符长度并存入LONG单元中。
源程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 DATA SEGMENT LONG DB 100 BUF DB 'ABCDEFGADE……' DATA ENDS STACK1 SEGMENT PARA STACK 'STACK' STA DB 100 DUP (?) STACK1 ENDS CODE SEGMENT ASSUME CS: CODE, DS: DATA, ES: DATA, SS:STACK1 START: MOV AX, DATA MOV DS, AX MOV ES, AX MOV CL, LONG LEA DI, BUF MOV BL, CL MOV AL, ‘D’ NEXT: CLD REPNE SCASB JZ FOUND JMP OVER FOUND: MOV SI, DI DEC DI PUSH DI PUSH CX CLD REP MOVSB DEC BL POP CX POP DI JMP NEXT OVER: MOV LONG, BL MOV AH, 4CH INT 21H CODE ENDS END START
4.字符统计
例、在数据区STRING地址开始存有一字符串,以“$”作为结尾标志,长度不超过250个字节。统计该字符串的长度,并存于LENG单元中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 源程序: DATA SEGMENT STRING DB 'ABCDEFGHIJKLM……' LENG DB ? DATA ENDS STACK1 SEGMENT PARA STACK 'STACK' STA DB 100 DUP (?) STACK1 ENDS CODE SEGMENT ASSUME CS: CODE, DS: DATA, SS: STACK1 START: MOV AX, DATA MOV DS, AX MOV CX, 0 LEA DI, STRING MOV AL, '$' NEXT: CMP AL, [DI] JZ OVER INC DI INC CX JMP NEXT OVER: MOV LENG, CL MOV AH, 4CH INT 21H CODE ENDS END START
三.表处理
表的应用很广泛,如有平方表、转移表、换码表等。表中可以存放一系列供机器执行的任务、一系列相关联的数据及执行结果,以供在各种情况下使用。
1)表查询
表查询有直接表查询、顺序表查询、折半表查询和散列值表查询等。
直接表查询是查询的内容正是表内要查项的地址,因而不用比较,直接取该地址的内容。如果该地址内容为非空则查找成功,否则为查找失败。这种查表法查找速度快,但要求表中各项内容是连续有序的。所以在设计表格时,应尽量满足这个要求。
四.检索
检索是在计算机数据处理中,特别是管理软件中经常使用的一种操作。检索就是在一组数据中寻找出需要的数据项。检索的过程,就是在数据组中找出具有给定关键字的过程。当找到时,称为检索成功;找不到,称检索失败。
实际使用的数据项,通常是一个记录,它包含有多个数据项。关键字不过只占用其中的一个或几个域。它能唯一地将各记录区别开。一般来说,无论哪个方面的检索系统,其信息量都是很大的。所以检索过程是很费时间的,所以检索算法的优劣将直接影响检索的速度。
1)顺序检索
顺序检索是一种简单的检索方法。这种检索方法是使用给出的关键字与数据序列中的各项关键字逐个进行比较,直到整个数据序列结尾。如果找到则检索成功,否则检索失败。
顺序检索常用来对无序数据序列进行检索。因为无序序列中关键字的排列没有任何规律,所以,必须从头开始逐一向后检索,以获得所要检索的项。
2)折半检索
折半检索也称二分检索,主要用于对已排序好的数据序列进行检索。其检索过程大致如下:设有一升序数据序列,首先用要检索的关键字与该数据序列的中间一项进行比较,如果相等则检索成功;如果不等则判断关键字是否小于中间项值,若小于则要查找的项位于数据序列前半部分,否则在后半部分。然后再在可能含有关键字的部分中间取一项与关键字比较,相等则检索成功,不等则重复上述操作,直至整个数据序列检索完毕。由于这种检索方法每次都将范围缩小一半,故称折半检索。
折半检索完成一次成功的查找平均进行的比较次数为log2 -1。 显然要比顺序检索法速度快得多。
在折半检索中,确定中间项是关键。下面讨论中间项的确定方法。
设一个数据序列包含N个数据,其第一个数据为下限数据,序号为1,用下限序号指针L表示。最后一个数据为上限数据,序号为N,用上限序号指针H表示。中间项数据序号M则可以由公式M=INT[(L+H)/2]得到。其中INT表示取整操作。当关键字与中间项比较之后,如果关键字包含在前半部分,则上限指针改为H=M-1,下限指针不变。如果关键字包含在后半部分,则上限指针不变,下限指针改为H=M+1。然后再根据上、下限的指针确定新的中间项。如此不断地确定中间项与关键字进行比较,直到找到或确知无此关键字为止。此时L>H。
例、在数据区BUF地址起有一组升序数据,长度为10字节。KEYWORD单元中为已知关键字。检索其在数据序列中的序号。若检索成功,序号送RESULT单元,否则RESULT单元置0FFH。
源程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 DATA SEGMENT BUF DB 09H, 23H, 45H, 68H, 90H DB 0A0H, 0ABH, 0C8H, 0D7H, 0F8H N DB 10 KEYWORD DB 90H RESULT DW ? DATA ENDS STACK1 SEGMENT PARA STACK 'STACK' STA DB 100 DUP (?) STACK1 ENDS CODE SEGMENT ASSUME CS: CODE, DS: DATA, SS; STACK1 START: MOV AX, DATA MOV DS, AX MOV BL, 1 ;置下限指针 MOV BH, N ;置上限指针 LEA DI, BUF MOV CL, KEYWORD NEXT: MOV AH, 0 MOV AL, BH ;取上限指针值 ADD AL, BL ;取下限指针值 SHR AL, 1 ;取中间项 MOV CH, AL ;暂存中间项 ADD AX, DI ;取中间项地址 MOV SI, AX CMP CL, [SI] ;与关键字比较 JZ FOUND ;找到,转FOUND MOV AL, CH ;取回中间值 JA BIG ;高转BIG DEC CH ;低于,修改上限指针 MOV BH, CH JMP LOW BIG: INC CH ;高于,修改下限指针 MOV BL, CH LOW: CMP BL, BH ;比较上下限指针 JA OVER ;下限指针大于上限指针,转结束 MP NEXT ;继续检索 FOUND: MOV RESULT, CH JMP OVER1 OVER: MOV RESULT, 0FFH OVER1: MOV AH, 4CH INT 21H CODE ENDS END START
五.排序
排序,是指对给定的一组元素,按规定的顺序进行排列。排序的目的就是为了检索提供方便。排序的方法很多,有交换排序、选择排序、插入排序、快速排序等。
常用思想:冒泡排序(“小数往上浮,大数往下沉”)
例、在内存BUF单元开始的区域中存放有一组无符号的字节数据,试编程序将这些数据按从小到大的顺序排序,排序后的数据依然放在原来的存储区中。
具体算法是:首先在一组数中进行第一轮比较,将第一个存储单元中的数与其后的N-1个数进行比较,若两个数不满足降序排列,则将两者交换,即总是将两数中较大者放在第一存储单元中。这样经过N-1次比较后,N个数中最大数就存入到第一个单元中,其中N-1次比较可以用计数型循环来控制;接着进行第二轮比较,将第二个存储单元中的数与其后的N-2个存储单元中的数依次进行比较,不满足降序则交换。这样经过N-2次比较后,N个数中的次大者就存入第二个存储单元中,……,如此重复下去,直到第N-l轮比较完成后,将N个数中的第(N-1)大者存入第N-1个存储单元中,剩下第N个存储单元中的数自然是最小者。这样经过N-1轮比较就可以实现N个数的降序排序,从第一轮到第N-1轮的控制又可以用一个计数型循环来实现。这样整个程序就要用到双重循环来控制实现,其中,外循环是用来控制是第几轮比较,内循环是用来控制每一轮中比较的次数。
源程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 DATA SEGMENT BUF DB 34H, 4BH, 22H, 1AH, 53H, 5DH N EQU $-BUF DATA ENDS CODE SEGMENT ASSUME CS: CODE, DS: DATA BEGIN: MOV AX, DATA MOV DS, AX MOV SI, 1 L1: MOV DI, SI INC DI MOV AL, [BUF+SI-1] L2: CMP AL, [BUF+DI-1] JAE L3 XCHG [BUF+DI-1], AL MOV [BUF+SI-1], AL L3: INC DI CMP DI, N JBE L2 INC SI CMP SI, N-1 JBE L1 MOV AH, 4CH INT 21H CODE ENDS END BEGIN