330 likes | 497 Views
第七章 简单程序设计应用. 7.1 串操作程序 7.2 代码转换 7.3 冒泡排序举例 7.4 多精度数运算举例. 7.1 串操作程序. 一、串操作指令. 串操作指令 :对串中的字节 / 字 / 双字进行传送、比较、搜索等。 串: 由连续存放于内存的若干个字节 / 字 / 双字组成的数据块。. 注意: 串操作指令寻址与其他指令有很大不同,其源操作数( 源串 )和目的操作数( 目的串 )分别隐含由 DS : [SI] 和 ES : [DI] 提供。其中源串可以是 DS 以外的其他段,但 目的串只能在 ES 段 。.
E N D
第七章 简单程序设计应用 7.1 串操作程序 7.2 代码转换 7.3 冒泡排序举例 7.4 多精度数运算举例
7.1 串操作程序 一、串操作指令 串操作指令:对串中的字节/字/双字进行传送、比较、搜索等。 串:由连续存放于内存的若干个字节/字/双字组成的数据块。 注意:串操作指令寻址与其他指令有很大不同,其源操作数(源串)和目的操作数(目的串)分别隐含由DS:[SI]和ES:[DI]提供。其中源串可以是DS以外的其他段,但目的串只能在ES段。
1、与REP匹配使用的MOVS、STOS、LODS指令。 • MOVS 串传送指令 格式:MOVS 目的串,源串 其中源串为SI指向的数据单元,目的串为DI所指向的附加段的数据单元。 所执行操作: 字节操作:[DI] ←[SI],SI←SI±1,DI←DI±1 字操作: [DI] ←[SI],SI←SI±2,DI←DI±2
MOVSB (字节传送指令) 功能:[DI] ←[SI],SI←SI±1,DI←DI±1 • MOVSW (字传送指令) 功能:[DI] ←[SI],SI←SI±2,DI←DI±2 • MOVSD (双字传送指令) 功能:[DI] ←[SI],SI←SI±4,DI←DI±4
STOS (串存储指令) 格式:STOS 目的串 其中目的串必须为DI所指向的数据单元。 执行的操作: 字节操作:[DI] ←AL ,DI←DI±1 字操作:[DI] ←AX, DI←DI±2 若已确定为字节操作或字操作,可采用无操作数指令。
STOSB (字节存储指令) 功能:[DI] ←AL ,DI←DI±1 • STOSW (字存储指令) 功能:[DI] ←AX,DI←DI±2 • STOSD (双字存储指令) 功能:[DI] ←EAX,DI←DI±4
LODS (串读取指令) 格式:LODS 源串 其中源串为SI 所指向的数据单元。 执行的操作: 字节操作:AL←[SI],SI←SI±1 字操作:AX←[SI],SI←SI±2 若已确定为字节或字操作,可采用无操作数指令。
LODSB (字节读取指令) 功能:AL←[SI],SI←SI±1 • LODSW (字读取指令) 功能:AX←[SI],SI←SI±2 • LODSD (双字读取指令) 功能:EAX←[SI],SI←SI±4
REP (重复串操作指令) 操作:①先判断CX=0?,若CX=0,退出REP操作,否则转②执行 ②CX←CX-1 ③执行相配合的串指令 重复①→③ • CLD 清除方向标志指令 格式:CLD 功能:DF←0,可使地址自动增1、增2或增4。
STD 清除方向标志指令 格式:STD 功能:DF←1,可使地址自动减1、减2或减4。 2、与REPE/REPZ和REPNE/REPNZ联合工作的CMPS和SCAS指令。 • REPE/REPZ(相等或为零时重复) 即CX=0或ZF=0时退出,否则CX←CX-1,重复执行。 • REPNE/REPNZ(不相等或不为零时重复) 即CX=0或ZF=1时退出,否则CX←CX-1,重复执行。
CMPS(串比较指令) 格式:CMPS 源,目;[SI]-[DI] • CMPSB 字节比较指令 功能:[SI]-[DI] ,SI←SI±1,DI←DI±1 • CMPSW 字比较指令 功能:[SI]-[DI] ,SI←SI±2,DI←DI±2 • CMPSD 双字比较指令 功能:[SI]-[DI] ,SI←SI±4,DI←DI±4
SCAS (串搜索指令) 格式:SCAS 目 用于搜索在数据块中是否存在某一关键字。 • SCASB (字节搜索指令) 功能:AL-[DI] ,DI←DI±1 • SCASW (字搜索指令) 功能:AL-[DI] ,DI←DI±2 • SCASD (双字搜索指令) 功能:AL-[DI] ,DI←DI±4
例:要把数据段1000开始的200个字节内容传送到1100H开始处。例:要把数据段1000开始的200个字节内容传送到1100H开始处。 • 用串处理指令来完成的程序段如下: MOV SI,1000H MOV DI,1100 MOV CX,200 MOV AX,DS MOV ES,AX CLD REP MOVSB
不用串处理指令,可用下列程序段代替REP MOVSB AGAIN:JCXZ STOP MOV AL,[SI] MOV [DI],AL INC SI INC DI JMP AGAIN STOP: ……
二、串操作程序 例:数据串传送程序,把SI缓冲区的数据依次传送到S2缓冲区中。 DATA SEGMENT S1 DB ‘AGIGDFSAASLJSFJSL’ LEN EQU $-S1 DATA ENDS EXTRA SEGMENT S2 DB LEN DUP(?) EXTRA SEGMENT
CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:EXTRA START:MOV AX,DATA MOV DS,AX MOV AX,EXTRA MOV ES,AX MOV SI,OFFSET S1 MOV DI,OFFSET S2 MOV CX,26 CLD REP MOVSB MOV AH,4CH INT 21H CODE ENDS END START
例:比较两个字符串,若相同,标志单元FLAG置0,否则置-1。例:比较两个字符串,若相同,标志单元FLAG置0,否则置-1。 DATA SEGMENT STR1 DB ‘ABCDEFGH’ STR2 DB ‘ABCDEFGH’ COUNT EQU $-STR2 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:DATA START:MOV AX,DATA
MOV DS,AX MOV ES,AX MOV SI,OFFSET STR1 MOV DI,OFFSET STR2 MOV CX,COUNT CLD REPZ CMPSB JNZ UNEQU MOV AL,0 JMP NEXT UNEQU:MOV AL,0FFH NEXT:MOV FLAG,AL MOV AH,4CH INT 21H CODE ENDS END START
例7.2查找指定字符串中是否含有子字符串,若有,则给RESU单元置子字符串在串中的偏移地址,否则给RESU单元置-1。例7.2查找指定字符串中是否含有子字符串,若有,则给RESU单元置子字符串在串中的偏移地址,否则给RESU单元置-1。 DATA SEGMENT STRING DB ‘this is an example’ TRLEN EQU $-STRING SUB DB ‘xamp’ SUBLEN EQU $-SUB RESU DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:DATA
INC AX MOV SI,AX DEC BX JNZ LOP MOV RESU,0FFH JMP EXIT Y: SUB AX,OFFSET STRING MOV RESU,AL EXIT: MOV AH,4CH INT 21H CODE ENDS END START START: MOV AX,DATA MOV DS,AX MOV EX,AX MOV BX,STRLEN LEA SI,STRING MOV AX,SI LOP: LEA DI,SUB MOV CX,SUBLEN CLD REPZ CMPSB JZ Y
7.2 代码转换 一、代码转换为数制 例7.5将ASCII码表示的八位二进制数转换成一字节二进制数。 其具体算法如下: 1)取一字节ASCII码的值放入BL中 2)BL←BL-30H ;转换成0或1 3)AL←AL∨BL 4)AL左移一位后仍放入AL中 5)重复上面的1)——4)步骤,直到8位二进制全部处理结束为止
程序代码如下: DATA SEGMENT BEGIN DB ‘11010001’ COUNT EQU $-BEGIN CLOSE DB ? DATA ENDS STACK SEGMENT PARA STACK‘STACK’ DB 10DUP(?) STACK EDNS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK
MAIN PROC FAR START:MOV AX,DATA MOV DS,AX LEA SI,BEGIN ;ASCII码串地址送SI MOV CX,COUNT ;循环次数送CX XOR AL,AL ;AL清0 AGAIN: SAL AL,1 MOV BL,[SI] ;取一个字符 INC SI ; 修改指针 SUB BL,30H ;转换为数值 OR AL,BL LOOP AGAIN
MOV CLOSE,AL RET MAIN ENDP CODE ENDS END START 2、数制转换为代码 例7.6将一字节二进制数转换成8字节二进制ASCII码字符串 。 程序清单如下:
DATA SEGMENT BEGIN DB 11011110B CLOSE DB 8 DUP(?) COUNT EQU $-CLOSE DATA ENDS CODE SEGMENT ASSUME DS:DATA,CS:CODE MAIN PROC FAR START:MOV CX,COUNT LEA DI,CLOSE AGAIN: MOV AL,30H MOV BL,BEGIN
TEST BL,10000000B ;测试BL中的最高位是否为0 JZ NEXT ;是,转NEXT INC AL ;否,AL=AL+1 NEXT: MOV [DI],AL ;存放结果 SAL BL,1 ;取BL的下一位 INC DI ;修改结果指针 LOOP AGAIN RET MAIN ENDP CODE ENDS END START
7.3 冒泡排序举例 算法: 具体实现过程:从第一个数开始依次对相邻两个数进行比较,如次序对则不做任何操作;如次序不对则使这两个数交换位置。表7.1表示了这种算法的例子,可以看出,在做了第一遍的(N一1)次比较后,最小的数已经放到了最后,所以第二遍比较只需要考虑(N一1)个数,即只需要比较(N一2)次,第三遍则只需要做(N一3)次比较……总共最多(N一1)遍比较就可以完成排序。
例7.8有一个首地址为a的N字数组,请编制程序使该数组中的数按照从大到小的次序整序。例7.8有一个首地址为a的N字数组,请编制程序使该数组中的数按照从大到小的次序整序。 ;冒泡排序程序清单如下: DATA SEGMENT;定义数据段 ARR DW 1,2,3,4,5,6,7,8,9,10,11,12,20 DW 18,14,17,16,15,13,19 COUT EQU($-ARRAY)/ 2 DATA ENDS CODE SEGMENT ;代码段开始 ASSUME CS:PROG,DS:DATA
START: MOV AX,DATA; ;设置数据段初值 MOV DS,AX MOV CX,COUT ;置循环次数 LAB1: MOV DI,CX MOV BX,0 LAB2: MOV AX,ARR[BX] ;取数组第一个数 CMP AX,ARR[BX+2] ;与第二个数比较 JGE CONTI ;大于转CONT1 XCHG AX,ARR[BX+2] ;交换顺序 MOV ARR[BX],AX
CONTI: ADD BX,2 ;取下一个数 LOOP LAB2 MOV CX,DI LOOP LAB1 MOV AH,4CH ;返回DOS INT 21H CODE ENDS ;代码段结束 END START
7.4 多精度数运算举例 例7.9 试编制一程序段,将一个多精度数变补。
程序段如下: XOR CH,CH ;CH清0 MOV BL,CL MOV DI,SI LP1: NOT BYTE PTR[SI] ;各位取反 INC SI ;指针加1 LOOP LP1 ;循环,直到处理完所有位数 MOV CL,BL STC ; 标志寄存器CF位置“1” LP2: ADC BYTE PTR[DI],0 ; 末位加1 INC DI LOOP LP2 ; 循环,直到处理完所有的位数