第02讲第四章程序设计的基本方法.ppt
1,第四章 程序设计的基本方法,4.1 概述,程序设计要点:分析问题的需求,选择好解决方法;针对选定的算法,编写高质量的程序。一个高质量的程序不仅要满足正确性的要求,而且还应尽可能实现以下几点:(1)结构清晰、简明、易读、易调试。结构好(2)执行速度快。效率高(3)占用存储空间少。资源少,2,汇编语言程序设计的一般步骤:(1)分析问题,选择合适的解题方法。(2)根据具体问题,确定输入输出数据的格式。(3)分配存贮区并给变量命名(包括分配寄存器)。(4)绘制程序的流程图,即将解题方法和步骤用程序流程图的形式表示出来。(5)根据流程图编写程序。(6)静态检查与动态调试,3,几种程序设计方法:顺序程序设计分支程序设计循环程序设计子程序的设计本章主要讲解:各种转移指令格式、功能及使用条件分支程序设计循环程序设计子程序的设计,本章主要讲述的内容,4,几种框图符号,1.起始、终止框 2判断框3处理说明框4子程序或过程调用框5.流向框6连接框,1,5,4.3.4 分支程序设计,分支程序的特点:根据不同情况作出不同的处理,程序结构分成了若干支路。分支的结构形式:(1)(2)结构特点:程序运行方向是向前的,条件确定,只能执行分支中的一个。机器根据不同的情况作出判定,有选择的执行相应的分支。这类程序称之为分支程序。,6,问题:计算机怎样判断这些分支?,(1)分支由条件转移指令产生,不同条件通过EFLAGS的标志位状态(0或1)反映出来;(2)转移指令不影响EFLAGS的标志位,可连续使用转移指令,产生多个分支。例:可以产生如下的多个分支。CMP BYTE PTR ARRAYBX,0 JLE L1;小于等于0,转移到L1 分支1;大于0L1:JL NEXT;小于0,转移到NEXT 分支2;等于0NEXT:分支3;小于0,7,4.3.4 分支程序设计要点,选择合适的转移指令;为每个分支安排出口;将分支中的公共部分尽量放到分支前或分支后的公共程序段中;流程图、程序对应;调试时,逐分支检查。,8,转移指令的特点,特点:(1)改变程序的执行顺序,即改变指令指针CS:IP/EIP的值;(2)不改变标志位。主要用于设计分支程序,关键在于根据需要,根据各个标志位的不同状态,选用合适的转移指令。,9,转移指令的分类,转移指令,条件转移,无条件转移,简单条件转移(10条),无符号数条件转移(4),有符号数条件转移(4),段内直接、段间直接,段内间接、段间间接,10,4.3.1 简单条件转移,根据单个标志位 CF、ZF、SF、OF、PF的值确定是否转移,之所以称之为简单条件,就是因为它只根据一个标志位进行跳转。,语句格式:,标号:操作符 短标号,短标号是一个标号。该标号代表条件成立时,想转移到的目的地址。若该目的地址与当前(IP)之间的字节距离在-128 127之间,则称该标号为短标号。,11,简单条件转移指令,JZ/JE ZF=1时,转移JNZ/JNE ZF=0时,转移JS SF=1时,转移JNS SF=0时,转移JO OF=1时,转移JNO OF=0时,转移JC CF=1时,转移JNC CF=0时,转移JP/JPE PF=1时,转移JNP/JPO PF=0时,转移,运算结果为0运算结果不为0运算结果为负数运算结果不为负数运算结果溢出运算结果没有溢出运算产生进位借位运算没有产生进位借位结果低8位1的个数为偶数结果低8为1的个数为奇数,12,JZ L1 MOV AX,0 L1:,ZF=1?,MOV AX,0,N,y,L1:,指令与流程图的对应关系,13,简单条件转移指令的特点,特点:根据单一标志位确定转移方向;当超出转移范围时,可用JMP搭桥;不能作段间转移,不得作间接转移;不影响EFLAGS的标志位,可连续使用转移指令,产生多个分支。,14,4.3.2 无符号数条件转移指令,无符号数条件转移指令往往跟在比较指令之后;根据与无符号数特征有关条件标志CF和ZF的组合决定转移方向。JA/JNBE 短标号 当 CF=0 并且 ZF=0时,转移(大于)JAE/JNB 短标号 当 CF=0 或者 ZF=1时,转移(大于等于)JB/JNAE 短标号 当 CF=1 并且 ZF=0时,转移(小于)JBE/JNA 短标号 当 CF=1 或者 ZF=1时,转移(小于等于),15,大于转(即不小于且不等于转)JA/JNBE 条件标志:CF=0且ZF=0时转移 用于两个无符号数a、b的比较,若ab则实现转移 查看a,b两数相减的结果:a-b CMP a,b CF(有没有借位)ZF(相不相等)a b a-b 0 0a=b a-b 0 1a b a-b 1 0一般用法:CMP OPD,OPS;(OPD)(OPS)转 JA P,16,大于或等于转(即不低于转)JAE/JNB 条件标志:CF=0或ZF=1时转移 即(OPD)(OPS)时转,等价于指令JNC(两数相等的时候ZF=1,那么CF=0)小于或等于转(即不高于转)JBE/JNA 条件标志:CF=1或ZF=1时转移 即(OPD)(OPS)时转,小于转(即不高于等于转)JB/JNAE 条件标志:CF=1且ZF=0时转移 即(OPD)(OPS)转 等价于指令 JC(因为CF=1,则ZF=0),17,无符号数条件转移指令的理解,CMP AX,BX JA L1 L1:,将(AX),(BX)中的数据当成无符号数,执行(AX)(BX)。若(AX)(BX),则CF一定会为0,ZF=0,转移到L1处。,例1:(AX)=1234H,(BX)=0234H,例2:(AX)=0A234H,(BX)=0234H,例3:(AX)=0A234H,(BX)=09234H,18,问题:CF和ZF标志位是否可以作为判断有符号数比较大小的标志位?来看两有符号数相减的结果:A-B,A,B取值有下列几种情况:,不能用CF、ZF的组合来判断有符号数的大小,而用SF、OF、ZF组合。,19,4.3.3 有符号数条件转移指令,JG/JNLE 短标号 当 SF=OF 并且 ZF=0时,转移(大于)JGE/JNL 短标号 当 SF=OF 或者 ZF=1时,转移(大于等于)JL/JNGE 短标号 当 SFOF 并且 ZF=0时,转移(小于)JLE/JNG 短标号 当 SFOF 或者 ZF=1时,转移(小于等于),20,小于转(或不大于等于转)JL/JNGE 功能:SFOF=1(SF OF)且ZF=0转(异或为1时转移)。(两数相减,差为负就说明(OPD)小于(OPS),为什么不仅仅判断SF=1,用JS呢?没有溢出时可以,有溢出的时候结果为正)设(OPD)-(OPS)有:SF OF SFOF0 0 00 1 11 0 11 1 0结果为正无溢出,说明OPD=OPS,不转移结果为正有溢出,说明真正结果应为负(OPD小),转移结果为负无溢出,说明OPDOPS,应转移结果为负有溢出,说明真正结果应为正,不转移,21,大于等于转(或不小于0转)JGE/JNL 条件:SF OF=0或ZF=1转移,即SF=OF或ZF=1转。用于两带符号数比较,若AB则条件满足,实现转移。大于转(或不小于等于转)JG/JNLE 条件:SF OF=0且ZF=0转,即SF=OF且ZF=0转。小于等于转(或不大于0转)JLE/JNLE 条件:SF OF=1或ZF=1转移,即SFOF或ZF=1转。,22,有符号数条件转移指令的理解,CMP AX,BX JG L1 L1:,将(AX),(BX)中的数据当成有符号数,执行(AX)(BX)。若(AX)(BX),则SF、OF会相等,ZF=0,转移到L1处。,例1:(AX)=1234H,(BX)=0234H,SF=0、OF=0,ZF=0,CF=0,不论使用 JA 还是 JG,转移的条件均成立,23,例2:(AX)=0A234H,(BX)=0234H,例3:(AX)=0A234H,(BX)=09234H,执行(AX)-(BX)后:SF=1,ZF=0,CF=1,OF=0,对于 JA,条件成立(CF=0,ZF=0),对于 JG,条件不成立(因为SFOF),SF=0,ZF=0,CF=0,OF=0,对于JA、JG,条件均成立,24,根据以上各条件指令的选用,可总结如下:1.简单转移指令用在TEST、CMP、AND、OR后面,测试某一标志位是否满足条件;用在算术运算指令后面,测试某一标志位是否满足条件;在循环计数控制中,用来判断循环是否结束,(JZ/JE/JNZ/JNE)。2.有符号数的条件转移指令用在CMP后面,比较带符号数大小,确定转移方向;用在算术运算指令后面,根据运算结果正负确定转移方向;用在OR,AND后面,根据结果正负确定转移方向。3.无符号数的条件转移指令用作无符号数的比较-地址的比较、ASCII码比较;用于循环控制。,25,到底选用哪条指令,这是由解题的要求和被判断对象的特点,如何理解?运算或者比较指令不管有符号数还是无符号数,它们根据运算结果既按照有符号数设置好标志位(OF、SF、ZF),同时也按照无符号数设置好标志位(CF、ZF),只等条件转移指令选择相应的标志位判断,进行转移。数字本身是有符号数还是无符号数,不由自身的写法决定,而由能够区分它们的指令决定(条件转移、MUL/IMUL)。若想按照有符号数处理,就选择有符号数的处理指令;若想按照无符号数处理,就选择无符号数的处理指令。要了解一条指令是否对于标志位是否真正起到影响作用。例:AX加1,如果产生了进位,转移到L1处。INC AX JC L1,INC指令不影响CF标志位,指令选择错误。,26,例:分析以下程序段,指出所完成的功能。DATA SEGMENT X DW n Y DW 0 OVERF DB 0AH,0DH,IS overflow!$DATA ENDS MOV Y,-1 MOV AX,X CMP AX,0 JZ EXIT1;X=0转EXIT1(将0-Y)ADD AX,1000H;如(X)0,则(X)+1000HAX JO OVER;溢出转OVER(打印字串,-1Y)JNS EXIT1;和为正转EXIT1 NEG AX;为负求补,即X的绝对值EXIT1:MOV Y,AX;结果(AX)YEXIT0:MOV AH,4CH INT 21HOVER:LEA DX,OVERF MOV AH,9 INT 21H JMP EXIT0,27,例1:从键盘输入09中任一自然数,求其立方值。若输入的字符不是09中的数字,则显示“Input Error!”,从键盘输入一个字符,是09中的某一个数,求其立方,显示输入错,结束,Y,开始,N,28,从键盘输入一个字符,是09中的某一个数,求其立方,显示输入错,结束,Y,N,程序是从上到下一行行编写的。从二维框图,向一维变迁。,29,从键盘输入一个字符,不是09中的数,求其立方,显示输入错,结束,N,y,条件成立时,一般的转移标号应与该指令有一段距离,条件不成立的处理分支,就在转移指令之下。,条件写法变迁,30,从键盘输入一个字符,(AL)0,求其立方,显示输入错,结束,N,y,(AL)9,N,y,条件细化,加标号,LERR:,EXIT:,c4_108_1.asm,31,例2:在例1的基础上显示出立方值。,显示立方值,可以使用“输出一个串”调用。构造一个串表,分别存放各立方值对应的ASCII串。如何构造?如何找到待显示串的起始位置?见程序:C4_108_2.asm,32,例3:根据输入的数字,显示对应的信息.0:zero 1:first 9:nine 其它:error 对于不同的输入,输出的串长度不同。,见程序:C4_108_3.asm,程序的关键:如何根据输入,将对应的待显示的串首址送DX。,33,格式:JMP 标号作用:使CPU无条件地转移到指令指明的目的地址处(标号指定)执行,转移的范围大,灵活性大;不能构成分支程序,但可将各分支的出口重新汇集在一起;CMP ARRAYBX,BYTE PTR 0 JLE L1;小于等于0,转移到L1 分支1;大于0 JMP GO1L1:JL NEXT;小于0,转移到NEXT 分支2;等于0 JMP GO1NEXT:分支3;小于0GO1:;所有分支汇集,4.3.5 无条件转移指令,34,某些条件转移指令转移的范围超过它规定的范围时,用JMP搭桥。例:JL L1;小于0时转L1超过了规定的转移范围 L1:可改为如下指令串:JGE L0;大于等于0时转L0 JMP L1;小于0时无条件转L1L0:L1:,4.3.5 无条件转移指令,35,根据所处的位置:段内转移:要转移的目的地址与指令本身在同一段;段间转移:要转移的目的地址与指令本身在不同段。根据寻址的方式:直接方式转移:转移到标号。间接方式转移:从存储器或寄存器中得到转移目的地的段地址和偏移地址。,4.3.5 无条件转移指令的分类,36,4.3.5 无条件转移指令,37,(1)段内直接跳转 格式:JMP 标号 功能:(IP/EIP)+相对位移量 IP/EIP 执行后 IP/EIP=标号的EA(2)段间直接跳转 格式:JMP 标号 或 JMP FAR PTR 标号 功能:标号所在段首址CS 标号的EAIP 以上寻址方式实际上均为立即寻址方式。段内直接跳转:JMP 0018 段间直接跳转:JMP 0ABC:0000,无条件转移指令,38,(3)段内间接跳转 格式:JMP OPD 功能:(OPD)IP/EIP 其中OPD为寄存器方式、存储器方式(寄存器间接、变址、基址变址、直接)寻址方式,OPD不能是立即数。如果是寄存器寻址方式,则16/32位寄存器的内容为偏移地址IP/EIP。16位段:16位寄存器的内容IP JMP AX 32位段:32位寄存器的内容EIP JMP EDX,无条件转移指令,39,(3)段内间接跳转 如果是存储器寻址方式,它实质是将由寻址方式得到的存储器内的操作数作为偏移地址IP/EIP。16位段:字类型变量/存储区的内容IP WBUF DW?JMP WBUF JMP WORD PTR BX,无条件转移指令,40,我们来看看几种作用等价的段内转移 ADDR16 DW?JMP GO2;直接转移 LEA BX,GO2 JMP BX;寄存器寻址的间接转移 LEA BX,GO2 MOV ADDR16,BX JMP ADDR16;直接寻址的间接转移 LEA BX,GO2 MOV ADDR16,BX LEA BX,ADDR16 JMP BX;寄存器间接寻址的间接转移GO2:,41,(4)段间间接转移 格式:JMP OPD 功能:(OPD)IP/EIP(OPD+2/4)CS 其中OPD只能为存储器寻址方式。此时地址信息必须用一双字(16位段)或,三字或四字(32位段)单元存放。对于16位段:双字类型变量/存储区的内容(OPD)IP,(OPD+2)CSJMP OPD OPD OPD+2 IP CS,42,看看几种作用等价的段间转移 ADDR32 DD?JMP FAR PTR GO3 JMP FGO3 MOV AX,OFFSET GO3 MOV BX,SEG GO3 MOV WORD PTR ADDR32,AX MOV WORD PTR ADDR32+2,BX JMP ADDR32;在另一个段内 FGO3 LABEL FARGO3:,43,例:无条件转移指令。JMP NEXT 直接方式的无条件转移指令JMP WORD PTR BX 段内间接转移指令(16位段)*JMP DWORD PTR BXDS:BX指向的双字单元中存放着EA和段首址(16位段),44,无条件转移指令中,若是间接方式,除了立即数寻址方式外,其它方式均可以使用。,设在数据段中有:BUF DW L1;L1为标号,JMP L1,(2)JMP BUF,LEA BX,BUF JMP WORD PTR BX,MOV BX,BUF JMP BX,功能等价的转移指令,45,注意:(1)条件转移指令,只能使用短标号,是段内转移,且转移的范围在128127个字节内。(2)无条件转移指令,可以是标号,也可以用某种寻址方式确定转移地址。转移范围不受限制。,设有如下程序段:JZ L1;ZF=0,对应的程序段AL1:.;ZF=1,对应的程序段B 若程序段A,B的长度均大于128个字节,怎么办?,JNZ L0 JMP L1L0:.;AL1:.;B,46,例4:根据不同的输入,执行不同的程序片段。,输入1,执行程序段 LP1:输入2,执行程序段 LP2:输入3,执行程序段 LP3:,JMP LP1JMP LP2.JMP LP3,如果分支很多,每个分支均使用 JMP 标号,程序难看,臃肿!,47,例5:段间直接转移指令,见:c4_108_5.asm,48,分支程序设计应该注意的问题,(1)选择合适的转移指令判断 x 中的内容,为正,显示 positive 0;为负,显示 0;为0,显示 zero,49,X 0?,lea dx,zero,Lea dx,positive,结束,Y,X 0?,Lea dx,negative,Y,N,N,见:c4_108_6.asm,50,条件控制流伪指令 P323,.IF 条件表达式 语句序列.ELSEIF 条件表达式 语句序列.ELSE 语句序列.ENDIF,条件表达式:关系运算=!=(2)逻辑运算&|,C4_108_7.ASM,51,X db-5为什么结果不正确?观察目标程序,发现其用的是无符号数比较转移指令。即masm6 将X当作无符号数来翻译的。若要将其当作有符号数,定义形式是:X SBYTE-5,同样,有SWORD,SDWORD,52,分支程序设计应该注意的问题(1),1.选择合适的转移指令。例:CMP AX,0 JL L1 能不能换成JB,JS;JB:CF=1且ZF=02.要为每个分支准备好出口。例:CMP AX,0 JGE L1 MOV DL,-L1:MOV DL,+,53,分支程序设计应该注意的问题(2),3.应将各分支的公共部分尽量提到分支前或分支后的公共程序段去执行,使程序简短、清晰。,54,分支程序设计应该注意的问题(3),4.分支比较多时,框图对每个分支的判断先后次序应尽量与问题提出的先后次序一致。而程序对各分支的安排也需要与框图的安排次序一致,这样在编写程序时就不会漏掉某一分支,而且写出的程序清晰,容易阅读和检查。5.在调试分支程序时,要假定各种可能的输入数据,沿着每一支路逐一检查,测试程序是否正确。只有所有分支都满足设计要求时,才能保证整个程序满足设计要求。,55,1.循环程序的结构,4.4 循环程序设计,计数控制、条件控制,2.循环控制方法,3.单重循环程序设计,4.多重循环程序设计,56,置循环初值部分,工作部分,修改部分,控制部分,已结束,未结束,循环程序的结构,57,设以BUF为首址的一片单元中,存放了N个有符号的字节数据。BUF DB 1,-10,20,-25,25,50,N=$-BUF 请找出其中的最大数,并存放到AL中。,将BUF视为数组AL BUF0FOR(i=1;iBUFi)ALBUFi;,58,程序 C4_113J1.asm,MOV AL,BUF MOV BX,1L1:CMP BX,N JGE EXIT CMP AL,BUFBX JGE L2 MOV AL,BUFBXL2:INC BX JMP L1EXIT:,若BUF中存放的字数据,程序应作何修改?最大数放在AX中。,59,程序 C4_113J2.asm,MOV AX,BUF MOV EBX,1L1:CMP EBX,N JGE EXIT CMP AL,BUFEBX*2 JGE L2 MOV AX,BUFEBX*2L2:INC BX JMP L1EXIT:,60,计数控制:循环次数已知时,常用(1)倒计数 将循环次数n,送入一循环计数器中,某循环一次,计数器减1,直到其值为0。,4.4.2 循环控制方法,MOV CX,循环次数LOOPA:DEC CX JNE LOOPA,61,计数控制:循环次数已知时,常用(2)正计数 循环次数n。0送入一循环计数器中,某循环一次,计数器加1,直到其值为n。,4.4.2 循环控制方法,MOV CX,0LOOPA:INC CX CMP CX,n JNE LOOPA,62,80X86提供的四种计数控制循环转移指令,4.4.2 循环控制方法,LOOP 标号(CX/ECX)-1 CX/ECX 若(CX/ECX)不为0,则转标号处执行。基本等价于:DEC CX/ECX JNZ 标号(LOOP指令对标志位无影响!)C4_115J.asm,63,80X86提供的四种计数控制循环转移指令,(2)LOOPE/LOOPZ 标号(CX/ECX)-1 CX/ECX 若(CX/ECX)不为0,且ZF=1,则转标号处执行,否则顺序执行。(等于或为0循环转移指令,本指令对标志位无影响),例:判断以BUF为首址的10个字节中是否有非0字节。C4_115J.asm,MOV CX,10 MOV BX,OFFSET BUF-1L3:INC BX CMP BYTE PTR BX,0 LOOPE L3,64,80X86提供的四种计数控制循环转移指令,(3)LOOPNE/LOOPNZ 标号(CX/ECX)-1 CX/ECX 若(CX/ECX)不为0,且ZF=0,则转标号处执行。(等于或为0循环转移指令,本指令对标志位无影响),例:判断以MSG为首址的10个字节中的串中是否有 空格 字符。C4_115J.asm,MOV CX,10 MOV BX,OFFSET MSG-1L4:INC BX CMP BYTE PTR BX,LOOPNE L4,65,80X86提供的四种计数控制循环转移指令,(4)JCXZ/JECXZ 标号;跳转指令格式:JCXZ/JECXZ 标号 Jump if CX is zero功能:当寄存器CX/ECX的值为0时转移到标号处执行,否则顺序执行。该指令常放在循环开始前,用于检查循环次数是否为0,为0时跳过循环体;也常与比较指令等组合使用,用于判断是由于计数值的原因还是由于满足比较条件而终止循环。MOV CX,COUNT JCXZ GO1L1:LOOP L1GO1:,66,关于使用循环控制指令LOOP需要注意的问题:使用固定的寄存器CX/ECX;所有的循环转移指令本身实施的对CX/ECX的值减1的操作不影响标志位;16位段的程序,LOOP、LOOPZ、LOOPNZ缺省使用CX寄存器;32位段程序,使用ECX寄存器;标号为短标号,即位移量只能为-128 127之间。,67,条件控制:循环次数未知。但是循环结束与某些条件(比较、运算的结果等等)相关,比较所要求的条件是否达到,未满足继续循环,否则结束循环。在解决实际问题时,往往要根据问题给定的已知条件,在认真分析算法之后才能确定选用哪种方法。,68,阅读程序段,指出其功能:MOV CL,0L:AND AX,AX JZ EXIT SAL AX,1 JNC L INC CL JMP LEXIT:,69,阅读程序段,指出其功能:MOV CL,0 MOV BX,16L:SAL AX,1 JNC NEXT INC CLNEXT:DEC BX JNZ L,70,例1:已知 有n个元素存放在以BUF为首址的 字节存储区中,试统计其中负数的个数,C4_117.asm,循环 n次;有些同学认为在循环体中,每次访问下一个单元,有:,L1:.INC BUF DEC CX JNZ L1,;将 BUF的地址加1,错误的原因,实质为将BUF的内容加1。,71,例2:以BUF为首址的字节存储区中,存放以$作结束标志的字符串。显示该串,并要求将其中的小写字母转换成大写字母显示。,见程序:c4_118.asm,72,例3:输入一个数字串,将其转换成字数据(即二进制形式),以16进制形式显示出来,见程序:c4_121_1.asm,(输入的串最长为5个字符,不考虑符号),输入缓冲区的定义转换方法(AX)存放转换的结果,初始为0。(SI)输入缓冲区指针,指向待转换字符 从上至下(即串从左到右)依次读入各字符,一边读入一边转换。设新字符为 X,则:(AX)10 X AX。即读入X后的结果。Try 123 的转换。,73,例:将一个无符号字节数转换成10进制形式显示。C4_121_2.asm,例6:将一个有符号字节数转换成10进制形式显示。C4_121_3.asm,74,循环程序设计中应该注意的问题:,比较不同指令次序,程序的运行结果C4_121_4.asm,75,1.子程序的概念,4.5 子程序设计,段内直接、段间直接段内间接、段间间接,2.子程序的调用与返回,3.子程序的定义格式及现场保护方法,4.主程序与子程序之间的参数传递,76,在编写程序时,常常出现如下情况:一段程序要被多次使用。例如“将一个二进制数转换成十进制的形式显示出来”。使用该段程序,也没有什么规律,怎么办?,F2T10:,想执行 F2T10,在执行完F2T10后,希望回到调用处继续执行,77,将经常要使用的或者重复的程序段设计成可供反复调用的独立程序段,在需要时,用控制指令调用它,在执行完后,再返回调用它的程序中继续执行。这样的独立程序段称为子程序。,调用子程序的程序称为主程序(或称调用程序)与主程序的关系:调用关系,调用之后又回到调用处的下一条指令。,78,K:调用子程序 ADK:J:调用子程序 ADJ:,子程序A,断点:转子指令的直接后继指令的地址。,子程序执行完毕,返回主程序的断点处继续执行,79,子程序设计中要解决的问题:1.怎样正确编写子程序?(定义)2.怎样正确调用子程序?3.主程序与子程序之间怎样传递参数?主程序每次调用子程序时提供给子程序加工的数据往往是不同的。主程序怎样把这些数据传送给子程序,而子程序又如何把加工的结果交给主程序?4.当主程序与子程序使用相同的寄存器时,应如何处理?(保护/恢复)5.子程序执行完之后,怎样才能返回到主程序的断点处继续往下执行?,80,子程序的定义,格式:子程序名 PROC 类型 过程体 子程序名 ENDP 子程序名也具有段属性,偏移地址属性和类型属性(FAR和NEAR(缺省)。NEAR类型为段内调用,即主子程序在同一个代码段内,子程序一般定义为NEAR,NEAR可省略。FAR类型为段间调用,被另外代码段调用的过程要定义为FAR过程(不管这两个代码段是否在一个模块中)。,81,子程序的调用和返回:CALL指令和RET指令,1.直接调用(1)段内直接调用 格式:CALL 子程序名 功能:(返回地址:跟在CALL后的下一条指令/断点的EA)(SP/ESP)目的地址(子程序名)EAIP/EIPCS:1010H CALL DISPCS:1013H INC SI CS:1138H DISP PROC NEAR,82,子程序的调用和返回:CALL指令和RET指令,2.段间直接调用格式:CALL FAR PTR 子程序名功能:(CS)(SP/ESP);跟在CALL后的下一条(IP/EIP)(SP/ESP);指令/断点的段首;址和偏移 目的地址(子程序名)的段首址CS 目的地址的(子程序名)EAIP/EIP1000H:1010H CALL FAR PTR DISP1000H:1013H INC SI 1200H:1138H DISP PROC FAR,83,转移指令的分类,转移指令,条件转移,无条件转移,简单条件转移(10条),无符号数条件转移(4),有符号数条件转移(4),段内直接、段间直接,段内间接、段间间接,84,简单条件转移指令,JZ/JE ZF=1时,转移JNZ/JNE ZF=0时,转移JS SF=1时,转移JNS SF=0时,转移JO OF=1时,转移JNO OF=0时,转移JC CF=1时,转移JNC CF=0时,转移JP/JPE PF=1时,转移JNP/JPO PF=0时,转移,运算结果为0运算结果不为0运算结果为负数运算结果不为负数运算结果溢出运算结果没有溢出运算产生进位借位运算没有产生进位借位结果低8位1的个数为偶数结果低8为1的个数为奇数,85,简单条件转移指令的特点,特点:根据单一标志位确定转移方向;当超出转移范围时,可用JMP搭桥;不能作段间转移,不得作间接转移;不影响EFLAGS的标志位,可连续使用转移指令,产生多个分支。,86,无符号数大小比较 CMP a,b CF(有没有借位)ZF(相不相等)a b a-b 0 0a=b a-b 0 1a b a-b 1 0CF:理解为够不够减。,87,有符号数大小比较,不能用CF、ZF的组合来判断有符号数的大小,而用SF、OF、ZF组合。,88,无符号数条件转移指令,无符号数条件转移指令往往跟在比较指令之后;根据与无符号数特征有关条件标志CF和ZF的组合决定转移方向。JA/JNBE 短标号当 CF=0 且 ZF=0时,大于转移 JAE/JNB 短标号当 CF=0 或者 ZF=1时,大于或等于转移 JB/JNAE 短标号当 CF=1 且 ZF=0时,小于转移 JBE/JNA 短标号当 CF=1 或者 ZF=1时,小于或等于转移,89,有符号数条件转移指令,JL/JNGE 短标号当 SFOF 且 ZF=0时,小于转移JLE/JNG 短标号当 SFOF 或者 ZF=1时,小于等于转移JG/JNLE 短标号当 SF=OF 且 ZF=0时,大于转移JGE/JNL 短标号当 SF=OF 或者 ZF=1时,大于等于转移,90,1.简单转移指令用在TEST、CMP、AND、OR后面,测试某一标志位是否满足条件;用在算术运算指令后面,测试某一标志位是否满足条件;在循环计数控制中,用来判断循环是否结束,(JZ/JE/JNZ/JNE)。2.有符号数的条件转移指令用在CMP后面,比较带符号数大小,确定转移方向;用在算术运算指令后面,根据运算结果正负确定转移方向;用在OR,AND后面,根据结果正负确定转移方向。3.无符号数的条件转移指令用作无符号数的比较-地址的比较、ASCII码比较;用于循环控制。,91,到底选用哪条指令,这是由解题的要求和被判断对象的特点,如何理解?运算或者比较指令不管有符号数还是无符号数,它们根据运算结果既按照有符号数设置好标志位(OF、SF、ZF),同时也按照无符号数设置好标志位(CF、ZF),只等条件转移指令选择相应的标志位判断,进行转移。数字本身是有符号数还是无符号数,不由自身的写法决定,而由能够区分它们的指令决定(条件转移、MUL/IMUL)。若想按照有符号数处理,就选择有符号数的处理指令;若想按照无符号数处理,就选择无符号数的处理指令。要了解一条指令是否对于标志位是否真正起到影响作用。例:AX加1,如果产生了进位,转移到L1处。INC AX JC L1,INC指令不影响CF标志位,指令选择错误。,92,格式:JMP 标号作用:使CPU无条件地转移到指令指明的目的地址处(标号指定)执行,转移的范围大,灵活性大;不能构成分支程序,但可将各分支的出口重新汇集在一起;某些条件转移指令转移的范围超过它规定的范围时,用JMP搭桥。根据所处的位置:段内转移:要转移的目的地址与指令本身在同一段;段间转移:要转移的目的地址与指令本身在不同段。根据寻址的方式:直接方式转移:转移到标号。间接方式转移:从存储器或寄存器中得到转移目的地的段地址和偏移地址。,无条件转移指令,93,无条件转移指令分类,94,(1)段内直接跳转 格式:JMP 标号 功能:(IP/EIP)+相对位移量 IP/EIP 执行后 IP/EIP=标号的EA(2)段间直接跳转 格式:JMP 标号 或 JMP FAR PTR 标号 功能:标号所在段首址CS 标号的EAIP 以上寻址方式实际上均为立即寻址方式。段内直接跳转:JMP 0018 段间直接跳转:JMP 0ABC:0000,无条件转移指令,95,(3)段内间接跳转 格式:JMP OPD 功能:(OPD)IP/EIP 其中OPD为寄存器方式、存储器方式(寄存器间接、变址、基址变址、直接)寻址方式,OPD不能是立即数。如果是寄存器寻址方式,则16/32位寄存器的内容为偏移地址IP/EIP。16位段:16位寄存器的内容IP JMP AX 32位段:32位寄存器的内容EIP JMP EDX,无条件转移指令,96,(3)段内间接跳转 如果是存储器寻址方式,它实质是将由寻址方式得到的存储器内的操作数作为偏移地址IP/EIP。16位段:字类型变量/存储区的内容IP WBUF DW?JMP WBUF JMP WORD PTR BX,无条件转移指令,97,我们来看看几种作用等价的段内转移 ADDR16 DW?JMP GO2;直接转移 LEA BX,GO2 JMP BX;寄存器寻址的间接转移 LEA BX,GO2 MOV ADDR16,BX JMP ADDR16;直接寻址的间接转移 LEA BX,GO2 MOV ADDR16,BX LEA BX,ADDR16 JMP BX;寄存器间接寻址的间接转移GO2:,98,(4)段间间接转移 格式:JMP OPD 功能:(OPD)IP/EIP(OPD+2/4)CS 其中OPD只能为存储器寻址方式。此时地址信息必须用一双字(16位段)或,三字或四字(32位段)单元存放。对于16位段:双字类型变量/存储区的内容(OPD)IP,(OPD+2)CSJMP OPD OPD OPD+2 IP CS,99,看看几种作用等价的段间转移 ADDR32 DD?JMP FAR PTR GO3 JMP FGO3 MOV AX,OFFSET GO3 MOV BX,SEG GO3 MOV WORD PTR ADDR32,AX MOV WORD PTR ADDR32+2,BX JMP ADDR32;在另一个段内 FGO3 LABEL FARGO3:,100,计数控制:循环次数已知时,常用(1)倒计数 将循环次数n,送入一循环计数器中,某循环一次,计数器减1,直到其值为0。,循环控制方法,MOV CX,循环次数LOOPA:DEC CX JNE LOOPA,101,计数控制:循环次数已知时,常用(2)正计数 循环次数n。0送入一循环计数器中,某循环一次,计数器加1,直到其值为n。,MOV CX,0LOOPA:INC CX CMP CX,n JNE LOOPA,循环控制方法,102,80X86提供的四种计数控制循环转移指令,(1)LOOP 标号(CX/ECX)-1 CX/ECX 若(CX/ECX)不为0,则转标号处执行。(2)LOOPE/LOOPZ 标号(CX/ECX)-1 CX/ECX 若(CX/ECX)不为0,且ZF=1,则转标号处执行,否则顺序执行。(3)LOOPNE/LOOPNZ 标号(CX/ECX)-1 CX/ECX 若(CX/ECX)不为0,且ZF=0,则转标号处执行。(4)JCXZ/JECXZ 标号;跳转指令 格式:JCXZ/JECXZ 标号;Jump if CX is zero 功能:当寄存器CX/ECX的值为0时转移到标号处执行,否则顺序执行。该指令常放在循环开始前,用于检查循环次数是否为0,为0时跳过循环体;也常与比较指令等组合使用,用于判断是由于计数值的原因还是由于满足比较条件而终止循环。,103,关于使用循环控制指令LOOP需要注意的问题:使用固定的寄存器CX/ECX;所有的循环转移指令本身实施的对CX/ECX的值减1的操作不影响标志位;16位段的程序,LOOP、LOOPZ、LOOPNZ缺省使用CX寄存器;32位段程序,使用ECX寄存器;标号为短标号,即位移量只能为-128 127之间。,104,子程序的定义,格式:子程序名 PROC 类型 过程体 子程序名 ENDP 子程序名也具有段属性,偏移地址属性和类型属性(FAR和NEAR(缺省)。NEAR类型为段内调用,即主子程序在同一个代码段内,子程序一般定义为NEAR,NEAR可省略。FAR类型为段间调用,被另外代码段调用的过程要定义为FAR过程(不管这两个代码段是否在一个模块中)。,105,子程序的调用和返回:CALL指令和RET指令,3.段内间接调用格式:CALL WORD PTR OPD(16位段)CALL DWORD