资源描述
本章内容: 掌握顺序结构程序的设计; 掌握分支转移指令的使用; 掌握分支程序和循环程序的设计方法。,第5章 基本结构程序设计,本章要求,1.掌握顺序结构程序的设计方法,能利用汇编语言基本指令熟练进行顺序结构程序设计; 2. 熟练掌握分支转移指令的使用,如何生成有效测试标志,选择何种方式的转移指令。 3. 掌握分支程序设计方法; 4. 掌握循环程序设计方法及串指令的应用。,本章重点及难点:,汇编指令的综合应用及多分支、多重循环程序设计。,计划学时: 8-10学时,顺序结构程序在设计上比较简单,它按指令书写的先后次序 执行一系列操作,这种程序也称为直线程序。,组成,输入数据,已知的数据,即让计算机进行运算的对象,处理,根据问题的需要对输入数据进行相应的运算处理,输出结果,将运算处理的结果输出,基本语句:数据传送指令、算术运算指令和逻辑运算指令,执行过程:,5.1 顺序结构程序设计,【例】:在屏幕上显示一个字符串:“WELCOME !”。,完整程序: DATA SEGMENT ;数据段开始 STRING DB WELCOME !,13,10,$ DATA ENDS ;数据段结束 CODE SEGMENT ;代码段开始 ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX ;设置DS MOV AH, 9 ;子功能号9,用于输出字符串 LEA DX,STRING ;字符串偏移地址 INT 21H ;系统功能调用 MOV AX,4C00H ;返回DOS INT 21H CODE ENDS ;代码段结束 END START,【例】:对于三个8位无符号数86H、34H和21H,编写 RESULT=86H*34H-21H的程序。,DATA SEGMENT NUM DB 86H,34H,21H RESULT DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX LEA SI,NUM MOV AL,SI MOV BL,SI+1 MUL BL ;乘积放在AX MOV BL,SI+2 MOV BH,0 ;把BX高位字节清零 SUB AX,BX MOV RESULT, AX ;保存运算结果 MOV AH,4CH INT 21H CODE ENDS END START,【例】:以BUF为首址的内存中存有015的平方值表。查表求X单元中数(在015之间)的平方值,并送回X单元。,DATA SEGMENT BUF DB 0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225 X DB 12 DATA ENDS STACK SEGMENT STACK STACK DB 100 DUP (?) STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK START:MOV AX,DATA MOV DS,AX MOV SI,OFFSET BUF XOR AX,AX MOV AL,X ADD SI,AX MOV AL,SI MOV X,AL MOV AH,4CH INT 21H CODE ENDS END START,转移的目标地址直接出现在指令中,功能:无条件地使程序转移到指定的目标地址,类型,段内转移,改变IP的值,CS的值不变,直接方式,间接方式,转移的目标地址在寄存器或存储单元中,段间转移,改变IP和CS的值,直接方式,间接方式,格式: JMP 目标标号,功能: IP IP + disp,格式: JMP 字地址指针,功能: IP EA,格式: JMP 目标标号,功能: IP OFFSET 目标标号 CS SEG 目标标号,格式: JMP 双地址指针,功能: IP EA CS EA+2,5.2.1 转移指令,5.2 分支程序设计,1. 无条件转移指令JMP,功能:以某些标志位或标志位的逻辑运算为依据,满足条件,程序转移 至指定目标;不满足条件,程序顺序执行。,注意:条件转移的目标地址 在+127或-128字节的范围之内,分类:1.单个标志位的条件转移指令 2.组合条件的条件转移指令,2. 条件转移指令,(1).单个标志位的条件转移指令,类型,C标志,JB/JNAE/JC,C=1时,转移,JAE/JNB/JNC,C=0时,转移,Z标志,JE/JZ,Z=1时,转移,JNE/JNZ,Z=0时,转移,S标志,JS,S=1时,转移,JNS,S=0时,转移,P标志,JP/PE,P=1时,转移,JNP/JPO,P=0时,转移,O标志,JO,O=1时,转移,JNO,O=0时,转移,(2).组合条件的条件转移指令,(3).CX的值为0转移指令,格式:JCXZ,CX=0,转移,说明:(1)条件转移指令不影响标志位 (2)条件转移指令前安排算术运算、比较、测试 等影响相应标志位的指令,无符号数: A 代表大于 B代表小于 带符号数:G代表大于 L代表小于,分支程序基本执行流程,【例】: 测试AX当前值是否为零,若为零,则置CX为50,否则令CX为200。,程序段一: CMP AX,0 JZ L MOV CX,200 JMP NEXT L: MOV CX,50 NEXT: ,;比较AX是否为0,;若AX为0,即ZF=1则转移,;若AX不为0,则令CX=200,;跳转到NEXT,程序段二: CMP AX,0 JNZ L MOV CX,50 JMP NEXT L: MOV CX,200 NEXT: ,【例】: 判断AX当前值的正负,若为正数,则置CX为50,否则令CX为200。,程序段一: CMP AX,0 JNS L MOV CX,200 JMP NEXT L: MOV CX,50 NEXT: ,;比较AX是否为0,影响SF标志,;若AX为正,即SF=0则转移,;若AX为负数,则令CX=200,;跳转到NEXT,程序段二: ADD AX,0 JS L MOV CX,50 JMP NEXT L: MOV CX,200 NEXT: ,程序段三(用ZF测试): TEST AX,8000H JNZ L MOV CX,50 JMP NEXT L: MOV CX,200 NEXT: ,程序段四(用CF测试): BT AX,15 JC L MOV CX,50 JMP NEXT L: MOV CX,200 NEXT: ,程序段五(用CF测试): SHL AX,1 JC L MOV CX,50 JMP NEXT L: MOV CX,200 NEXT: ,【例】: 已知X为16位的数,判断X是奇数还是偶数,若为奇数,则令Z=X,若为偶数,令Z=0。,程序段一(用ZF测试): MOV AX,X TEST AX,1 JNZ L MOV Z,0 JMP NEXT L: MOV Z,AX NEXT: ,程序段二(用CF测试): MOV AX,X BT AX,0 JC L MOV Z,0 JMP NEXT L: MOV Z,AX NEXT: ,SHR AX,1,【例】: 已知W为16位的数,若W为正数,则令Z=W,若为0,令Z=400H,若为负数,则Z=|W|+50H。,流程图片段,程序段一: MOV AX,W CMP AX,0 JZ L1 JNS L2 NEG AX ADD AX,50H MOV Z,AX JMP NEXT L2: MOV Z,AX JMP NEXT L1: MOV Z,400H NEXT: ,程序段二: MOV AX,W CMP AX,0 JNZ L1 MOV Z,400H JMP NEXT L1: JNS L2 NEG AX ADD AX,50H MOV Z,AX JMP NEXT L2: MOV Z,AX NEXT: ,【例】:如果 X50,转到TOO_HIGH,不满足,X-Y;如果溢出转到 OVERFLOW,否则 |X-Y| RESULT 。,JO,JNS,程序段如下: MOV AX, X CMP AX, 50 JG TOO_HIGH ;大于则转移到TOO_HIGH SUB AX, Y OVERFLOW ;溢出则转移 NONNEG ;结果为正则转移 NEG AX NONNEG: MOV RESULT, AX TOO_HIGH: OVERFLOW: ,【例】:已知X为一个带符号数,比较X的值,若X大于55H,则令Y=X/2-30H,若X小于-1,则令Y=|X|,否则,Y=0。编程解决该问题。,MOV AX,X CMP AX,55H ;第一次比较 JG XGY ;大于则转移 CMP AX,-1 ;第二次比较 JL XLY ;小于则转移 MOV Y,0 ;令Y=0 JMP EXIT XLY: NEG AX ;求绝对值 MOV Y,AX ;结果送到Y JMP EXIT XGY: SAR AX,1 ;大于,则执行Y=X/2-30H SUB AX,30H MOV Y,AX ;结果送到Y EXIT: ,5.2.2 双分支结构程序,1.双分支结构程序的典型结构,双分支结构程序的典型结构一,双分支结构程序的典型结构二,条件产生 在进行条件测试以前,必须执行能生成状态标志的先行指令,如:TEST、CMP、ADD、SUB、AND、OR、XOR和移位指令等,这些指令执行后能按规定影响PSW中的状态标志位OF,SF,ZF,PF与CF。为条件检测作好准备。 测试与定向 条件转移指令自动对相应的状态标志位进行测试,以确定是否满足条件,决定程序的不同走向。而每一条条件转移指令,恰好有两种选择,转移或顺序执行。 标号 对于每个分支,在转移的目标地址处一定要给出标号。,需注意的问题,2.双分支结构程序设计举例,【例】:设计字符比较程序,两个字符相同时,显示YES;否则显示NO,DATA SEGMENT D1 DB A D2 DB B RES1 DB YES, $ RES2 DB NO, $ DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV AL,D1 MOV BL,D2,CMP AL,BL JNE NEXT1 LEA DX,RES1 JMP NEXT2 NEXT1: LEA DX,RES2 NEXT2: MOV AH,09H INT 21H MOV AH,4CH INT 21H CODE ENDS END START,【例】:设存储单元A和B各有一无符号字节数,比较大小,将较大数送A单元,DATA SEGMENT A DB 39H B DB 0B4H DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV AL,A CMP AL,B JNC NEXT XCHG AL,B MOV A,AL NEXT: MOV AH,4CH INT 21H CODE ENDS END START,【例】 比较两个带符号字节数的大小,找出两个数中大的存入MAX字节单元,编写源程序如下: DATA SEGMENT DA1 DB X1,X2 ; X1,X2为任意二个带符号数 MAX DB ? DATA ENDS STAK SEGMENT STACK DW 20H DUP(?) STAK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV AL,DA1 ;取X1,送到AL中 CMP AL,DA1+1 JGE L1 ;若XX2则转到L1,这里产生分支 MOV AL, DA1+1 ;若XX2则DA1+1的内容送AL L1: MOV MAX,AL MOV AH,4CH INT 21H CODE ENDS END START,5.2.3多分支结构程序设计,含义:程序有两个以上的分支,设计方法:双分支方法、地址表法、转移表法、逻辑分解法,结构:,1.由多个双分支结构实现多分支结构程序设计,【例】:计算符号函数SNG(X)的值,DATA SEGMENT X DB 0B9H Y DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV AL,X CMP AL,0 JL NEXT1 ;X0则转NEXT2 MOV Y,0 ;X=0则令Y=0 JMP RES,源程序如下:,NEXT1: MOV Y,0FFH JMP RES NEXT2: MOV Y,1 RES: MOV AH,4CH INT 21H CODE ENDS END START,2.转移表法多分支程序设计,设计方法:把转移到各分支程序段的转移指令依次存放在一起,形成转移表。各转移指令在表中的位置: 离表首地址的偏移量作为转移条件,偏移量加上表首地址作为转移地址,转到表的相应位置,执行相应的无条件转移指令,典型例子: JMP BX TAB: JMP SHORT MODE0 ;转移表 JMP SHORT MODE1 JMP SHORT MODE2 JMP SHORT MODE3 JMP SHORT MODE4 ,说明:转移表中每条转移指令(段内短转移)占用2个字节,所以有如下计算公式: 表地址=模式字*2+转移表首地址,【例】:根据输入值(04)的不同,执行不同的操作,用转移表法编写程序,CODE SEGMENT ASSUME CS:CODE START: LEA BX,BRATAB ;取转移表首地址 MOV AH,1 INT 21H ;从键盘接收一个字符 SUB AL,30H ;ASCII数值 MOV AH,0 ADD AX,AX ;AX乘2 ADD BX,AX ;获取跳转地址 JMP BX BRATAB:JMP SHORT MODE0 ;转移表 JMP SHORT MODE1 JMP SHORT MODE2 JMP SHORT MODE3 JMP SHORT MODE4,MODE0:MOV DL,30H JMP EXIT MODE1:MOV DL,31H JMP EXIT MODE2:MOV DL,32H JMP EXIT MODE3:MOV DL,33H JMP EXIT MODE4:MOV DL,34H EXIT:MOV AH,2 INT 21H MOV AH,4CH INT 21H CODE ENDS END START,3.利用地址表法实现多分支程序设计,设计方法:把各分支程序段的入口地址依次存放在数据段的一个表中,形成地址表。取各分支程序段的编号作为各分支入口地址的表地址的位移量。某个分支程序入口地址的表地址为: 表地址=编号*2+入口地址首地址, ADTAB DW ADDR0,ADDR1,ADDR2,ADDR3,ADDR4 LEA BX, ADTAB ;取转移表首地址 MOV AL, NUM ;NUM数值送AL MOV AH,0 SHL AX, 1 ;AX乘2 ADD BX,AX ;获取跳转地址 JMP BX,【例】:根据NUM(04)的不同,执行不同的操作,用地址表法编写程序,DATA SEGMENT NUM DB 2 ADTAB DW ADDR0,ADDR1,ADDR2,ADDR3,ADDR4 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX, DATA MOV DS, AX LEA BX, ADTAB ;取转移表首地址 MOV AL, NUM ;NUM数值送AL MOV AH,0 SHL AX, 1 ;AX乘2 ADD BX,AX ;获取跳转地址 JMP BX,ADDR0:MOV DL,30H JMP EXIT ADDR1:MOV DL,31H JMP EXIT ADDR2:MOV DL,32H JMP EXIT ADDR3:MOV DL,33H JMP EXIT ADDR4:MOV DL,34H EXIT:MOV AH,2 INT 21H MOV AH,4CH INT 21H CODE ENDS END START,MOV AL, NUM ;NUM数值送AL MOV AH,0 SHL AX, 1 ;AX乘2 MOV SI, AX JMP ADTABSI,4.逻辑分解法多分支程序设计,设计方法:将多分支结构采用逻辑等效的方法,按条件的先后,依次分解成所示的一串双分支结构,然后使用双分支的方法来进行程序设计。,NEXT0:MOV DL,30H JMP EXIT NEXT1:MOV DL,31H JMP EXIT NEXT2:MOV DL,32H JMP EXIT NEXT3:MOV DL,33H JMP EXIT NEXT4:MOV DL,34H EXIT:MOV AH,2 INT 21H MOV AH,4CH INT 21H CODE ENDS END START,DATA SEGMENT NUM DB 2 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV AL,NUM CMP AL,0 JZ NEXT0 CMP AL,1 JZ NEXT1 CMP AL,2 JZ NEXT2 CMP AL,3 JZ NEXT3 CMP AL,4 JZ NEXT4,【例】:根据AL中的值(04),执行不同的操作,用逻辑分解法编写程序。,【例】: 已知有四个16位带符号数W、X、Y和Z,试编写程序,若四个数中有一个为0,则把另外三个单元清零;若四个数都不为0,则求其累加和(不考虑溢出),并保存到BUF单元中。,参考程序: DATA SEGMENT W DW ? ; 定义变量 X DW ? Y DW ? Z DW ? BUF DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA,分支程序设计综合举例,START: MOV AX,DATA MOV DS,AX CMP X, 0 JZ ZERO CMP Y,0 JZ ZERO CMP Z,0 JZ ZERO CMP W,0 JZ ZERO MOV AX, W ADD AX,X ;四个数累加 ADD AX,Y ADD AX,Z MOV BUF,AX JMP NEXT,;置四个数为0 ZERO: MOV W,0 MOV X,0 MOV Y,0 MOV Z,0 NEXT: MOV AH,4CH INT 21H CODE ENDS END START,【例】字节变量BUFX和BUFY存放整数,试编写完成指定下列操作的程序: (1) 若两个数中有一个是奇数,则将奇数存入BUFX字节单元中,偶数存入BUFY字节单元中; (2) 若两个数均为奇数,则两数分别加1,并存回原变量单元中; (3) 若两个数均为偶数,则两变量内容不变。 程序清单: DATA SEGMENT BUFX DB X BUFY DB Y DATA ENDS STAK SEGMENT STACK DW 20H DUP(?) STAK ENDS,CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV AL,BUFX ; 取X MOV BL,BUFY ; 取Y XOR AL,BL TEST AL,01H ; 测试X与Y是否同类 JZ L1 ; D0=0,则为同类转L1处理 TEST BL,01H ;非同类,测试Y是偶数否? JZ DONE ;是偶数满足(1),转DONE XCHG BL,BUFX ;奇数存入BUFX单元 MOV BUFY,BL ;偶数存入BUFY单元 JMP DONE L1: TEST BL,01H ;同类,测试Y是偶数否 JZ DONE ;同为偶数,满足(3)不变,转DONE INC BUFX ;是奇数两数同时各加1,存原单元。 INC BUFY DONE: MOV AH,4CH INT 21H CODE ENDS END SRTART,已知OPER1和OPER2为16位带符号数,分析下面程序段功能。 MOV AX,OPER1 MOV BX,OPER2 MOV CX,0 CMP AX,0 JNL L1 NEG AX L1: ADD CX,AX CMP BX,0 JNL L NEG BX L: ADD CX,BX 程序段完成的功能是: 。,CX|OPER1|+|OPER2|,课 堂 练 习,LOOP指令相当于以下两条指令的组合: DEC CX JNZ LABEL,功能: CX-10,循环;否则退出循环,类型,LOOP,格式: LOOP LABEL,循环直到计数为0,LOOPZ/LOOPE,格式: LOOPZ/ LOOPE LABEL,功能: CX-10 ZF=1,循环;否则退出循环,为零/相等则循环,LOOPNZ/ LOOPNE,格式: LOOPNZ/ LOOPNE LABEL,功能: CX-10 ZF=0,循环;否则退出循环,不为零/不相等则循环,5.3 循环结构程序设计,5.3.1 循环控制指令,指令系统专门设计了几条控制循环的指令。循环结构的实现方法是: MOV CX,N ;置循环次数,N事先要定义 AGAIN: ;循环体 DEC CX JNZ AGAIN 1 LOOP(Loop)循环指令 指令格式:LOOP OPR 测试条件:CX0则继续循环,CX0退出循环 LOOP指令规定:将CX作为计数寄存器,当执行LOOP指令时,它一定是将CX的内容减1,如CX结果不等于零,则转到LOOP指令中指示的短标号处;否则,顺序执行LOOP下一条指令。因此,在循环程序开始前(初始化),应将循环次数送到CX寄存器,这是指令本身的要求,不可违反。LOOP指令的操作数只能是一个短标号,即转移距离不可超过128127的范围。,【例】在STR开始的缓冲区中存放有一个字符串,结束符 $,计算该字符串的长度并存入LEN单元.,DATA SEGMENT STR DB JHHJK123ABCD$ LEN DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX LEA SI, STR ;取字符串首地址 XOR BL,BL ;用于统计长度 LOP:MOV AL,SI CMP AL,24H JZ STOP INC BL INC SI JMP LOP STOP:MOV LEN,BL MOV AH,4CH INT 21H CODE ENDS END START,【例】求以BUF为首地址的10个内存单元的无符号数据和。已知其和小于等于255,将结果存入第11个内存单元。,DATA SEGMENT BUF DB 12H,38H,46H,0BH,09H,41H,32H,56,02H,26H RES DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV AL,0 ;用于存放累加结果 MOV CX,0AH ;设置循环次数 LEA BX,BUF LP: ADD AL,BX ;累加求和 INC BX ;指向下一单元 LOOP LP MOV RES,AL MOV AH,4CH INT 21H CODE ENDS END START,2 LOOPZLOOPE(loop while zero,or egual)当为零或相等时循环指令 指令格式:LOOPZ(或LOOPE)OPR 执行循环条件:CX0且ZF1 退出循环条件:ZF0或CX0 本指令的操作也是先将CX寄存器的内容减1,仅当CX0且ZF1时转移到LOOPZ指令指定的短标号处继续循环。LOOPZLOOPE指令本身对状态标志位没有影响,应该由先行指令提供状态标志,如CMP、TEST等指令。这条指令是有条件地形成循环,即当规定的循环次数尚未完成时,还要满足“相等”或者“等于零”的条件,才能继续循环。 3 LOOPNZLOOPNE(loop while nonzexo or not egual)不为零或不相等时循环指令。 指令格式:LOOPNZ(或LOOPNE)OPR 执行循环条件:CX0且ZF0 退出循环条件:ZF1或CX0,【例】在字节数组中找出第一个非0的数据,并将其下标存入RES单元,假设其下标值小于10。,DATA SEGMENT ARR DB 0,0,38H,46H DB 89H,67H,0H,92H CNT EQU $ARR RES DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV CX,CNT MOV DI,-1 AGAIN:INC DI CMP ARRDI,0 LOOPZ AGAIN JZ EXIT MOV RES,DI EXIT:MOV AH,4CH INT 21H CODE ENDS END START,(1)先执行后判断(非0次循环结构),(2)先判断后执行(0次循环结构),5.3.2 循环程序的结构,【例】在以BUF为首地址的字节单元中存放了CNT个无符号数,找出其中最大数送入MAX字节单元。,DATA SEGMENT BUF DB 1,2,3,100,23,78,90,134 CNT EQU $-BUF ;BUF数组元素个数 MAX DB ? DATA ENDS,【分析】:可把第一个数先送到AL中,将AL中的数与后面的CNT-1个数逐个进行比较,如果AL中的数大于或等于与之相比较的数,则转下一个数进行比较;若AL中的数小于相比较的数,则把相比较的数送入AL中,保证AL中的数始终处于较大的数。比较CNT-1次之后最大数必定在AL中,最后把AL中的数送入MAX单元。本例的特点:循环次数已知,因此可以用计数器来控制循环的执行。程序编写如下:,CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AX,DATA MOV DS,AX ;设置DS MOV CX,CNT-1 ;设置比较次数 LEA BX, BUF ;取BUF数组首地址 MOV AL,BX ; 设第一个数为最大值 LOOP1: INC BX ;移动指针,指向下一个数 CMP AL,BX JAE NEXT ;大于等于则转移 MOV AL,BX ;小于则把数送AL NEXT: DEC CX JNZ LOOP1 MOV MAX,AL ;最大值送MAX MOV AH,4CH INT 21H CODE ENDS END START,5.3.3 循环程序设计方法,1.用计数器控制循环,含义:利用循环次数作为控制条件 应用场合:循环次数已知 分类:正计数法和倒计数法 设计方法:初值放入CX,【例】已知数据块的长度,统计数据块中正数和负数的个数,DATA SEGMENT BUF DB 32,25,36,-18,-64,0,-3 COUNT EQU $-BUF PLUS DB ? ;存放正数 MINUS DB ? ;存放负数 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START:MOV AX,DATA MOV DS,AX MOV BL,0 ;负数个数 MOV DL,0 ;正数个数 MOV SI,OFFSET BUF MOV CX,0 ;循环初值 LOP1:MOV AL,SI ;取值,CMP AL,0 JG NEXT0 JZ NEXT1 INC BL JMP NEXT1 NEXT0:INC DL NEXT1:INC SI INC CX CMP CX,COUNT JL LOP1 MOV MINUS,BL MOV PLUS,DL MOV AH,4CH INT 21H CODE ENDS END START,【例】已知数据块的长度,统计数据块中正数和负数的个数,DATA SEGMENT BUF DB 32,25,36,-18,-64,0,-3 COUNT EQU $-BUF PLUS DB 0 ;存放正数 MINUS DB 0 ;存放负数 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START:MOV AX,DATA MOV DS,AX LEA SI, BUF MOV CX,COUNT ;循环次数 LOP1: MOV AL,SI ;取值,CMP AL,0 JG NEXT0 JZ NEXT1 INC MINUS JMP NEXT1 NEXT0:INC PLUS NEXT1:INC SI LOOP LOP1 MOV AH,4CH INT 21H CODE ENDS END START,倒计数法程序设计举例,【例】将BUF单元开始的100个字节存储单元全部清0,DATA SEGMENT BUF DB 100 DUP (?) DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV BX,OFFSET BUF MOV CX,64H LP:MOV BYTE PTR BX,0 INC BX LOOP LP MOV AH,4CH INT 21H CODE ENDS END START,2.按问题的条件控制循环,含义:用转移指令来判断循环条件 应用场合:循环次数是不知道或不确定,按问题条件控制循环程序设计举例,【例】记录某个字节存储单元数据中1的个数,并把结果存入RES单元,DATA SEGMENT NUM DB 75H RES DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV BL,NUM XOR DL,DL AGAIN:TEST BL,0FFH JZ NEXT SHR BL,1 ADC DL,0 JMP AGAIN NEXT: MOV RES,DL MOV AH,4CH INT 21H CODE ENDS END START,3.用逻辑变量控制循环,含义:用转移指令来判断循环条件 应用场合:控制转入不同的循环支路 方法:把逻辑变量送入寄存器中,以逻辑变量各位的状态作为执行某段 程序的标志,按逻辑变量控制循环程序设计举例,【例】在以BUF为起始地址的内存中放有若干单字节无符号数,假定逻辑变量的长度为一个字节,它的D0 D7 位对应着BUF BUF+7单元内容的运算。某位为0,则将相应单元内容的D7位复制到D6位,其他位不变;某位为1,则将相应单元内容之高低四位互换。假定逻辑变量的值是10010101,ROL AL,CL JMP RES NEXT:PUSH AX AND AL,80H SAR AL,1 MOV DL,AL POP AX AND AL,3FH OR AL,DL RES:MOV BX,AL INC BX DEC AH JNZ LP MOV AH,4CH INT 21H CODE ENDS END START,DATA SEGMENT BUF DB 75H,12H,87H,98H,81H,56H,73H,51H B EQU 8 C EQU 10010101 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA STT:MOV AX,DATA MOV DS,AX MOV AH,B MOV CH,C LEA BX,BUF LP:MOV AL,BX SHR CH,1 JNC NEXT MOV CL,4,含义:指循环体内还有循环,也就是循环嵌套 注意:(1) 不允许循环结构交叉 (2)转移指令只能从循环结构内转出或可在同层循环内转移,5.3.4 多重循环程序设计,【例】设在以EXST为首址的存储区中依次存放着某考区245个理科生的七门成绩,现要统计每个考生的总成绩,并将其存放在该考生单科成绩之后的两个单元.,DATASEGMENT EXST DB 01,75,82,84,92,78,49,85,00,00 DB 02, 85,81,94,92,68,69,95,00,00 DB 245, 78,88,89,96,77,79,80,00,00 DATAENDS CODESEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV BL,245 ;外循环次数 LEA SI,EXST LOP2: MOV CX,7 ;内循环次数 XOR AX,AX INC SI ;指向当前学生成绩 LOP1: ADD AL,SI,245名学生7门课程成绩,ADC AH,0 INC SI LOOP LOP1 MOV WORD PTR SI,AX INC SI INC SI DEC BL JNZ LOP2 MOV AH,4CH INT 21H CODEENDS END START,【例】将N个不同的无符号数a1,a2,.,an由小到大进行排序。若每个数占一 个字, 则N个数可定义如下: A DW a1,a2,a3,.,an。它们的内存分配分别为A0,A2,A4,.,A2n,CMP AX,ABX+SI JNA L1 XCHG AX,A BX+SI MOV ABX,AX L1:ADD SI,2 LOOP LOOP2 ADD BX,2 MOV CX,DX LOOP LOOP1 MOV AH,4CH INT 21H CODE ENDS END START,DATA SEGMENT A DW 1223,83,456,355,948,789CNT EQU $-A/2 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV CX,CNT-1 MOV BX,0 LOOP1:MOV DX,CX MOV SI,2 LOOP2:MOV AX,ABX,【例】: 已知字符串MESS1中包含50个互不相等的字符,字符串MESS2中包含30个互不相等的字符,找出既在MESS1中出现,也在MESS2中出现的字符,组合成一一新的字符串,保存到STRING中,并把新字符串长度保存在COUNT。,分析: 需要使用两重循环实现。 从MESS1中取一个字符,与MESS2逐个比较,符合要求的送STRING。 重复这个过程,直到完成为止。,DATA SEGMENT MESS1 DB AB7DTB5 ; 共50个字符 MESS2 DB 9DACFG ;共30个字符 STRING DB 30 DUP (?) ;给STRING分配存储空间 COUNT DB ? ;用于统计新字符串字符数 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AX,DATA MOV DS,AX LEA SI, MESS1 ;MESS1首地址送SI LEA BX,STRING ;STRING首地址送BX MOV CX,50 ;MESS1长度,作为外循环次数 MOV COUNT,0 ;用COUNT统计STRING长度,参考程序,AGAIN: MOV AL,SI ;从MESS1中取出一个字符 PUSH CX ;CX入栈 MOV CX,30 ;MESS2长度,内循环次数 LEA DI,MESS2 ;MESS2首地址送DI CONTI: CMP AL,DI ;比较两个字符是否相等 JNZ NEXT MOV BX,AL ;相等把字符送STRING INC BX ;指针指向下一个存储单元 INC COUNT ;字符串长度加1 JMP EXIT1 ;退出内循环 NEXT: INC DI ; 指向下一个字符 LOOP CONTI EXIT1: POP CX INC SI LOOP AGAIN CODE ENDS END START,1. 串操作指令,(1).与REP相匹配的MOVS、STOS、LODS指令,1)MOVS 串传送指令,MOVS,MOVSB,格式: MOVSB 功能:(DI)(SI) SISI1 DIDI1,MOVSW,格式: MOVSW 功能:(DI)(SI) SISI2 DIDI2,MOVSD,格式: MOVSD 功能:(DI)(SI) SISI4 DIDI4,5.3.5 串操作程序,串传送指令不加REP前缀而单独使用时,必须事先设置好五个条件: 数据段的段寄存器DS赋值(可段超越); 附加段的段寄存器ES赋值; 取源串存储单元的首地址或末地址送入SI源变址寄存器中; 取目标串存储单元的首地址或末地址送入DI目标变址寄存器中; 根据选定的增址方向设DF=0(默认方向),减址方向设DF=1。 串传送指令不影响状态标志位。,2)STOS 串存储指令,STOS,STOSB,格式: STOSB 功能:(DI)AL DIDI1,STOSW,格式: STOSW 功能:(DI)AX DIDI2,STOSD,格式: STOSD 功能:(DI)EAX DIDI4,存入串指令单独使用时,事先必须准备好四个条件: (1) 目标串的段寄存器ES要赋值(不可超越); (2) 目标串的数据区首地址或末地址必送至DI; (3) 待送入存储单元的数据要先存入AL、AX或EAX累加器中; (4) 按地址增减方向设置方向标志DF的值。,3)LODS 串读取指令,LODS,LODSB,格式: LODSB 功能: AL (SI) SISI1,LODSW,格式: LODSW 功能: AX (SI) SISI2,LODSD,格式: LODSD 功能: EAX (SI) SISI4,其中,当 DF=0时取“”号,当 DF=1时取“-”号。 从串取指令单独使用时,预先必须设置好三个条件: DS(可跨越) SI DF,【例】 在DS=3000H的内存中,以BUFFER为首地址的存储区内,存放10个十进制数的ASC码,将这些十进制数顺序显示在屏幕上。,根据题意,主要程序段如下: MOV AX,3000H MOV DS,AX ;对DS赋值,条件 LEA SI,BUFFER ;取源串首地址,条件 CLD ;设DF=0增址方向,条件 MOV CL,10 ;字节串长度 MOV AH,02H ;AH单字符显示功能号 LOP:LODSB ;AL从串取一个字符 MOV DL,AL ;要显示字符要送入DL中 INT 21H ;DOS功能调用,此处显示一个字符 DEC CL ;修改循环数 JNZ LOP ;未完成10个字符显示则重复 ,4)重复操作前缀,REP,格式: REP 功能: 若CX=0,则退出REP操作,否则转执行 CXCX-1 执行REP后面的一次 转回执行,可以是MOVS、STOS、LODS,5)清除方向标志指令,CLD,格式: CLD 功能: DF0,6)设置方向标志指令,STD,格式: STD 功能: DF1,存入串指令STOS可以与REP联用,数据串的长度送到CX寄存器中,以控制重复执行的次数。它可使规定长度的字节单元或字单元设置相同的数值。 【例】在ES=1000H的附加段中,将从BUF为首地址的100个字节单元内容清零,可编写主要程序段如下: MOV AX,1000H MOV ES,AX ;条件1 LEA DI,BUF ;条件2 MOV AL,0 ;条件3 MOV CX,100 ;条件4 CLD ;条件5,必须设以上五个条件 REP STOSB ;可重复100次操作,从串取指令LODS也允许与REP联用,实际上,LODS指令一般不与REP联用,不然一串数据送入AL或AX中,到结束时,只有最后一个数据留在AL或AX中,这样的数据串连续取在一个寄存器中是毫无意义的。但是不用REP前缀,LODS指令可以将一串数据通过AL或AX进行一些处理,再用STOB指令送回存储器,但必须用循环程序,而不能使用REP LODS指令来完成。 串操作指令与重复前缀配合使用,这不仅可以简化程序,而且提高了运行速度。 【例】 将数据段中首地址为BUF1的200个字节数据传送到附加段中首地址为BUF2开始的内存区中,设DS=1000H,ES=2000H,试用以下三种要求来编制程序: (1) 用一般的MOV指令; (2) 用串操作指令MOVSB; (3) 用LODSB与STOSB指令。,要求一的程序段:使用MOV指令的程序段: MOV AX,1000H ; MOV DS,AX ;数据段赋值 MOV AX,2000H ; MOV ES,AX ;附加段赋值 LEA BX,BUF1 ;取源数据区首址 LEA SI,BUF2 ;取目标数据区首址 MOV CX,200 ;传送的字节数 LOP: MOV AL,BX ;取源数据 MOV ES:SI,AL ;存数 INC BX ; INC SI ;调整地址指针 DEC CX ;调节循环次数 JNZ LOP ;CX0继续循环,要求二的程序段:使用MOVSB指令的程序段: MOV AX,1000H MOV DS,AX ;设置DS MOV AX,2000H MOV ES,AX ;设置ES LEA SI,BUF1 ;设置SI(源串) LEA DI,BUF2 ;设置DI(目的串) MOV CX,200 ;重复次数 CLD ;增量 DF=0 REP MOVSB ;重复200次传送操作 注意:为使指令REP MOVSB的执行,必须设置好相关条件,方能达到预期结果。,要求三的程序段:使用LODSB和STOSB指令的程序段: MOV AX,1000H MOV DS,AX ;LODSB 指令条件1 MOV AX,2000H MOV ES,AX ;STOSB指令条件1 LEA SI,BUF1 ;LODSB指令条件2 LEA DI,BUF2 ;STOSB指令条件2 CLD ;两指令共同条件3 MOV CX,200 ;置循环数 LOP: LODSB STOSB DEC CX JNZ LOP,
展开阅读全文