子程序调用与返回(对照转移指令理解)CALL属性LABEL格式:1、CALLNEARPTRLABEL(段内调用)CALLLABEL(段内直接调用)CALLr16/m16(段内间接调用)2、CALLFARPTRLABEL(段间直接调用)CALLDWORDPTRm32(段间间接调用)RET(分成段内和段间两种情况)RETi16串操作类指令在程序设计中,经常需要对内存中一个连续区域的数据(如数组、字符串等)进传送、比较等操作。为了更好地支持这种数据类型的操作,8088CPU设计了串操作指令,同时还有重复前缀可以实现循环。MOVS(Movestring)串传送CMPS(Comparestring)串比较SCAS(Scanstring)串扫描LODS(Loadformstring)从串中取STOS(Storeintostring)存入串与上述基本指令配合使用的前缀:REP(Repeat)重复REPZ/REPE(Repeatwhilezero/equal)为零/相等则重复REPNZ/REPNE(Repeatwhilenotzero/notequal)不为零/不相等则重复串操作指令采用了特殊的寻址方式,说明如下:1、源操作数用寄存器SI作为间址寻址,默认在数据段DS中,即DS:[SI];允许段超越。2、目的操作数用寄存器DI作为间址寻址,默认在附加段ES中,即ES:[DI];不允许段超越。3、每执行一次串操作,源地址指针SI和目的地址指针DI将自动修改:±1或±2;对于以字节为单位的串操作指令,地址指针应该±1,对于以字为单位的串操作指令,地址指针应该±2。4、当DF=0(执行CLD指令),地址指针应+1或+2;5、当DF=1(执行STD指令),地址指针应-1或-2;1、传送数据串§串传送指令MOVS:将数据段中的一个字节或字数据,传送到附加段的内存单元。有三种格式:MOVSmem,mem(或MOVSdst,src)MOVSB;字节串传送:ES:[DI]DS:[SI];然后:SISI±1,DIDI±1MOVSW;字串传送:ES:[DI]DS:[SI];然后:SISI±2,DIDI±2对于第一种格式,应在操作数中表明是字还是字节传送:MOVSES:BYTEPTR[DI],DS:[SI]使用MOVS指令时要特别注意传送的方向。如果源串和目的串不重叠,采用哪种传送方向都一样。如果源串和目的串部分重叠,则传送的方向为:如果源串的起始地址低于目的串的起始地址,则应自动减量(DF=1);如果源串的起始地址高于目的串的起始地址,则应自动增量(DF=0)。§串存储指令STOS:将AL或AX的内容存入附加段的内存单元。STOSdst(mem);dstAL或AXSTOSB;字节串存储:ES:[DI]AL;然后:DIDI±1STOSW;字串存储:ES:[DI]AX;然后:DIDI±2§串读取指令LODS:将数据段中的一个字节或字数据读到AL或AX寄存器。LODSsrc(mem);AL或AXsrcLODSB;字节串读取:ALDS:[SI];然后:SISI±1LODSW;字串读取:AXDS:[SI];然后:SISI±2§重复前缀指令REP用在MOVS、STOS指令之前,利用CX作为计数器保存数据串的长度,可以理解为“当数据串没有结束(CX≠0),则继续传送”。REP串指令;每执行一次串指令,CX=CX-1;直到CX=0,重复执行结束。使用REP前缀,应做好以下准备工作:1)将存放于数据段中的源串首地址(若反向传送应是末地址)存入SI寄存器中;2)将存放于附加段中的目的串首地址(若反向传送应是末地址)存入DI寄存器中;3)数据串的长度存入CX寄存器中;4)建立方向标志。下面两条指令用于建立方向标志:CLD(Cleardirectionflag)是使DF=0,执行串指令后地址自动增量;STD(Setdirectionflag)是使DF=1,执行串指令后地址自动减量;数据段DS附加段ES低地址高地址SIDI对于DF=0SIDI对于DF=1[例]在数据段有一字符串,其长度为17,要求传送到附加段。datasegment;定义数据段mess1db‘personalcomputer’dataendsextrasegment;定义附加段mess2db17dup(?)extraendscodesegmentassumecs:code,ds:data,es:extrastart:movax,datamovds,axmovax,extramoves,axleasi,mess1leadi,mess2movcx,17cldrepmovsbmovah,4chint21hcodeendsendstart2、检测数据串这组串操作指令实现对数据串的比较CMPS和扫描SCAS。由于串比较和串扫描实质上是进行减法运算,所以它们像减法指令一样影响标志。这两个串操作指令可以配合重复前缀REPE/REPZ和REPNE/REPNZ,通过ZF标志说明两数是否相等。l串比较指令CMPS:用源数据串减去目的数据串,以比较两者间的关系。CMPSmem,mem(或者CMPSdst,src)CMPSB;字节串比较:DS:[SI]-ES:[DI];然后:SISI±1,DIDI±1CMPSW;字串比较:DS:[SI]-ES:[DI];然后:SISI±2,DIDI±2•串扫描指令SCAS:用AL/AX的内容减去目的数据串,以比较两者间的关系。SCASdst(mem)SCASB;字节串扫描:AL-ES:[DI];然后:DIDI±1SCASW;字串扫描:AX-ES:[DI];然后:DIDI±2•重复前缀指令REPE或REPZ用在CMPS、SCAS指令之前(中间至少要有一个空格),利用CX保存数据串的长度,同时判断比较是否相等,可以理解为“当数据串没有结束(CX≠0),并且串相等(ZF=1),则继续进行比较”,指令格式如下:REPZ/REPE串比较或串扫描指令执行的操作为:①若CX=0或者ZF=0,重复执行结束。②CX=CX-1。③执行其后的串操作指令。④重复①~③。l重复前缀指令REPNE或REPNZ用在CMPS、SCAS指令之前(中间至少要有一个空格),利用CX保存数据串的长度,同时判断比较是否不相等,可以理解为“当数据串没有结束(CX≠0),并且串不相等(ZF=0),则继续进行比较”,指令格式如下:REPNZ/REPNE串比较或串扫描指令执行操作:①若CX=0或者ZF=1,重复执行结束。②CX=CX-1。③执行其后的串操作指令。④重复①~③。注意:重复执行结束的条件是“或”的关系,只要满足条件之一就可结束。当指令执行完成,可能数据串还没有比较完,也可能数据已经比较完,编程时需要加以区分。InstructionMnemonicDestinationSourcePrefixmovestringbyteMOVSBES:DIDS:SIREPmovestringwordMOVSWES:DIDS:SIREPstorestringbyteSTOSBES:DIALREPstorestringwordSTOSWES:DIAXREPloadstringbyteLODSBALDS:SInoneloadstringwordLODSWAXDS:SInonecomparestringbyteCMPSBES:DIDS:SIREPE/REPNEcomparestringwordCMPSWES:DIDS:SIREPE/REPNEscanstringbyteSCASBES:DIALREPE/REPNEscanstringwordSCASWES:DIAXREPE/REPNEStringOperationSummary:[例]在介绍循环控制指令时举的例子:将数据段SBUF指示的1KB的数据传送到附加段DBUF缓冲区。可以改写成如下程序段:MOVCX,400H;循环次数:1024=400HLEASI,SBUFLEADI,DBUFCLD;规定DF=0,地址增量循环REPMOVSB;重复字节传送:ES:[DI]DS:[SI];如果设置CX=200H,则用REPMOVSWSTOS串操作的典型应用是初始化某一内存区域。例如将附加段64KB内存全部初始化为0的程序段:MOVDI,0MOVAX,0MOVCX,8000H;CX32*1024REPSTOSW;重复字传送:ES:[DI]0★DF的值无关紧要![例]挑出数组中的正数(不含0)和负数,分别形成正数数组和负数数组。假设数组ARRAY具有COUNT个字,正数组为AYPLUS,负数组为AYMINUS,它们都在数据段中。编写程序段如下:DATASEGMENTCOUNTEQU10ARRAYDW0023H,8000H,0F300H,……AYPLUSDWCOUNTDUP(0)AYMINUSDWCOUNTDUP(0)DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATA,ES:DATAMOVAX,DATAMOVDS,AXMOVES,AX;DS=ESLEASI,ARRAYLEADI,AYPLUSLEABX,AYMINUSMOVCX,COUNTAGAIN:LODSW;从ARRAY中取一数据到AXCMPAX,0JLMINUSJZNEXT;零不是正数,也不是负数。STOSW;大于0,是正数,存入AYPLUSJMPNEXTMINUS:XCHGBX,DISTOSW;将负数存入AYMINUSXCHGBX,DINEXT:LOOPAGAIN……