版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第五章循环与分支程序设计§5.1循环与转移指令§5.2循环程序设计§5.3分支程序设计第五章循环与分支程序设计§5.1循环与转移指令一、循环控制指令二、转移指令控制转移类指令通过改变IP(和CS)值,实现程序执行顺序的改变§5.1循环与转移指令一、循环控制指令控制转移类指令通过改一、循环控制指令8086指令系统的循环控制指令均为二字节指令一字节为转移的相对位移量(8位带符号的二进制数) IP←IP+相对位移量
EIP←EIP+相对位移量隐含使用CX作为循环计数器
程序中的某段需反复执行若干次时,用循环来实现短转移一、循环控制指令8086指令系统的循环控制指令均为二字节指令LOOPlabel
;CX←CX-1,CX≠0,循环到标号label一、循环控制指令LOOPE/LOOPZlabel ;CX←CX-1,CX≠0且ZF=1,循环到标号labelLOOPNE/NZlabel ;CX←CX-1,CX≠0且ZF=0,循环到标号label等于时循环不等于时循环LOOPlabel 一、循环控制指令LOOPE/L一、循环控制指令(例) MOVCX,COUNT ;设置循环次数
MOVSI,OFFSETDATA_BYTE XORAX,AX ;BX清0,用于存放累加和AGAIN: ADDAL,[SI] ADCAH,0
INCSI LOOPAGAIN ;计数器减1,不为0继续循环一、循环控制指令(例) MOVCX,COUNT ;设置循一、循环控制指令(例) MOVCX,COUNT ;设置循环次数
MOVSI,OFFSETSTRING XORBX,BX ;BX清0,用于记录空格数
MOVAL,20HAGAIN: CMPAL,[SI] JNZNEXT ;ZF=0,非空格,转移
INCBX ;ZF=1,是空格,个数加1 NEXT: INCSI LOOPAGAIN ;计数器减1,不为0继续循环一、循环控制指令(例) MOVCX,COUNT ;设置循二、转移指令无条件转移指令条件转移指令二、转移指令无条件转移指令 JMPlabel
;程序转向label标号指定的地址NEARFAR只要执行无条件转移指令JMP,就使程序转到指定的目标地址处,从目标地址处开始执行那里的指令JMP指令分成4种类型:⑴段内转移、直接寻址⑵段内转移、间接寻址⑶段间转移、直接寻址⑷段间转移、间接寻址目的地址与JMP属同一逻辑段,只修改IP值从一个代码段转移到另一个代码段,CS和IP都会被修改无条件转移指令 JMPlabel NEAR只要执行无条件转1.
无条件转移指令
—目标地址的寻址方式直接寻址方式转移地址象立即数一样,直接在指令的机器代码中,就是直接寻址方式间接寻址方式转移地址在寄存器或主存单元中,就是通过寄存器或存储器的间接寻址方式用标号表达用寄存器或存储器操作数表达1.无条件转移指令
—目标地址的寻址方式直接寻址方1.
无条件转移指令
—目标地址的范围:段内段内转移——近转移(near)在当前代码段64KB范围内转移
(±32KB范围)不需要更改CS段基值,只要改变IP偏移地址段内转移——短转移(short)转移范围可以用一个字节表达,在段内-128~+127范围的转移代码段代码段1.无条件转移指令
—目标地址的范围:段内段内转移1.无条件转移指令
—目标地址的范围:段间段间转移——远转移(far)从当前代码段跳转到另一个代码段,可以在1MB范围需要更改CS段基值和IP偏移地址目标地址必须用一个32位数表达,叫做32位远指针,它就是逻辑地址代码段代码段实际编程时,汇编程序会根据目标地址的距离,自动处理成短转移、近转移或远转移程序员可用操作符short、nearptr或farptr强制1.无条件转移指令
—目标地址的范围:段间段间转移——远段内直接寻址转移JMPlabel ;IP←IP+位移量位移量是紧接着JMP指令后的那条指令的偏移地址,到目标指令的偏移地址的地址位移当向地址增大方向转移时,位移量为正;向地址减小方向转移时,位移量为负实际为相对寻址
JMPAGAIN ;转移到AGAIN处继续执行
…… AGAIN: DECCX ;标号AGAIN的指令
……
JMPOUTPUT ;转向OUTPUT …… OUTPUT: MOVRESULT,AL ;标号OUTPUT的指令段内直接寻址转移JMPlabel ;IP←IP段内间接寻址转移JMPr16/m16 ;IP←r16/m16将一个16位寄存器或主存字单元内容送入IP寄存器,作为新的指令指针,但不修改CS寄存器的内容
JMPAX ;IP←AX JMPWORDPTR[BX] ;IP←[BX]段内间接寻址转移JMPr16/m16 ;IP←r段间直接寻址转移JMPfarptrlabel
;IP←label的偏移地址 ;CS←label的段基值将标号所在段的段基值作为新的CS值,标号在该段内的偏移地址作为新的IP值;程序跳转到新的代码段执行JMPFARPTROTHERSEG
;远转移到代码段2的otherseg段间直接寻址转移JMPfarptrlabel段间间接寻址转移JMPfarptrmem
;IP←[mem],CS←[mem+2]用一个双字存储单元表示要跳转的目标地址。这个目标地址存放在主存中连续的两个字单元中的,低位字送IP寄存器,高位字送CS寄存器MOVWORDPTR[BX],0MOVWORDPTR[BX+2],1500HJMPFARPTR[BX];转移到1500H:0段间间接寻址转移JMPfarptrmem2.条件转移指令Jcclabel
;条件满足,发生转移:IP←IP+8位位移量;条件不满足,顺序执行指定的条件cc如果成立,程序转移到由标号label指定的目标地址去执行指令;条件不成立,则程序将顺序执行下一条指令操作数label是采用短转移,称为相对寻址方式2.条件转移指令Jcclabel指定的条件cc如果成立,程2.条件转移指令Jcc指令的操作数label是一个标号一个8位位移量是相对于当前IP的,且距当前IP地址-128~+127个单元的范围之内,属于段内短距离转移Jcc指令为2个字节,条件不满足时的顺序执行就是当前指令偏移指针IP加22.条件转移指令Jcc指令的操作数label是一个标号2.条件转移指令—指令的分类Jcc指令不影响标志,但要利用标志。根据利用的标志位不同,19条指令分成4种情况:⑴判断单个标志位状态⑵比较无符号数高低⑶比较有符号数大小⑷判断计数器CX为02.条件转移指令—指令的分类Jcc指令不影响标志,但要利用助记符标志位助记符标志位JCCF=1JA/JNBECF=0且ZF=0JNCCF=0JAE/JNBCF=0或ZF=1JZ/JEZF=1JB/JNAECF=1且ZF=0JNZ/JNEZF=0JBE/JNACF=1或ZF=1JSSF=1JG/JNLESF=OF且ZF=0JNSSF=0JGE/JNLSF=OF或ZF=1JP/JPEPF=1JL/JNGESF≠OF且ZF=0JNP/JPOPF=0JLE/JNGSF≠OF或ZF=1JOOF=1JCXZCX=0JNOOF=0
实际虽然指令只有19条,但却有31个助记符
采用多个助记符,只是为了方便记忆和使用助记符标志位助记符标志位JCCF=1JA/JNBECF=0且判断单个标志位状态这组指令单独判断5个状态标志之一⑴JZ/JE和JNZ/JNE:利用零标志ZF,判断结果是否为零(或相等)⑵JS和JNS:利用符号标志SF,判断结果是正是负⑶JO和JNO:利用溢出标志OF,判断结果是否产生溢出⑷JP/JPE和JNP/JPO:利用奇偶标志PF,判断结果中“1”的个数是偶是奇⑸JC和JNC:利用进位标志CF,判断结果是否进位或借位例题例题例题例题例题
判断单个标志位状态这组指令单独判断5个状态标志之一例题例2.条件转移指令—JZ/JNZ指令 REPZCMPSB ;重复比较两个字符
JNZUNMAT
;ZF=0(不等),转移
MOVAL,0 ;顺序执行(相等)
JMPOUTPUT UNMAT: MOVAL,0FFH OUTPUT: MOVRESULT,AL
REPZCMPSB ;重复比较两个字符
JZMAT ;ZF=1(相等),转移
MOVAL,0FFH ;顺序执行(不等)
JMPOUTPUT MAT: MOVAL,0 OUTPUT: MOVRESULT,AL2.条件转移指令—JZ/JNZ指令 REPZCMPS2.条件转移指令—JS/JNS指令计算|X-Y|(绝对值)。X和Y为存放于X单元和Y单元的16位操作数,结果存入RESULT。
MOVAX,X SUBAX,Y JNSNONNEG NEGAX NONNEG: MOVRESULT,AX2.条件转移指令—JS/JNS指令计算|X-Y|(绝对值2.条件转移指令—JO/JNO指令计算X-Y。X和Y为存放于X单元和Y单元的16位操作数,若溢出,则转移到OVERFLOW处理
MOVAX,X SUBAX,Y JOOVERFLOW ... ;无溢出,结果正确OVERFLOW: ...
;有溢出处理2.条件转移指令—JO/JNO指令计算X-Y。X和Y为存放2.条件转移指令—JP/JNP指令设字符的ASCII码在AL寄存器中。将字符加上奇校验位:在字符ASCII码中为“1”的个数为奇数时令其最高位为“0”,否则令最高位为“1”
ANDAL,7FH;最高位置“0”,同时判断“1”的个数
JNPNEXT ;个数已为奇数,则转向NEXT
ORAL,80H
;否则,最高位置“1” NEXT: ...2.条件转移指令—JP/JNP指令设字符的ASCII码在A2.条件转移指令—JC/JNC指令记录BX中1的个数
XORAL,AL ;AL=0,CF=0 AGAIN: TESTBX,0FFFFH ;等价于CMPBX,0 JZNEXT SHLBX,1 JNCAGAIN INCAL JMPAGAIN NEXT: ... ;AL保存1的个数2.条件转移指令—JC/JNC指令记录BX中1的个数 2.条件转移指令
—无符号数的比较无符号数的大小用高(Above)低(Below)表示利用CF确定高低、利用ZF标志确定相等(Equal)两数的高低分成4种关系:⑴高于(不低于等于):JA
(JNBE)⑵高于等于(不低于):JAE
(JNB)⑶低于(不高于等于):JB(JNAE)⑷低于等于(不高于):JBE(JNA)2.条件转移指令
—无符号数的比较无符号数的大小用高2.
条件转移指令
—无符号数的比较(例) CMPAX,BX ;比较AX和BX JAENEXT ;若AX≥BX,转移
XCHGAX,BX ;若AX<BX,交换 NEXT: ...结果:AX保存较大的无符号数2.条件转移指令
—无符号数的比较(例) CMP2.条件转移指令
—有符号数的比较有符号数的大(Greater)小(Less)需要组合OF、SF标志,并利用ZF标志确定相等(Equal)两数的大小分成4种关系:⑴小于(不大于等于):JL(JNGE)⑵小于等于(不大于):JLE(JNG)⑶大于(不小于等于):JG
(JNLE)⑷大于等于(不小于):JGE
(JNL)2.条件转移指令
—有符号数的比较有符号数的大(G2.
条件转移指令
—有符号数的比较(例) CMPAX,BX ;比较AX和BX JGENEXT ;若AX≥BX,转移
XCHGAX,BX ;若AX<BX,交换 NEXT:...结果:AX保存较大的有符号数2.条件转移指令
—有符号数的比较(例) CMP2.
条件转移指令
—计数器CX为0转移 JCXZlabel;CX=0,发生转移:IP←IP+8位位移量;CX≠0,顺序执行CX寄存器通常在程序中用做计数器JCXZ指令用来判断计数是否为02.条件转移指令
—计数器CX为0转移 JCXZ§5.2循环程序设计一、循环程序的结构形式二、循环程序设计三、多重循环程序设计§5.2循环程序设计一、循环程序的结构形式
结束
初始化
循环的初始状态
循环体
循环的工作部分及修改部分
计数控制循环条件控制循环修改部分控制条件YN先循环,后判断一、循环程序的结构形式结束初始化循环的初一、循环程序的结构形式
结束
初始化
循环的初始状态
循环体
循环的工作部分及修改部分
计数控制循环条件控制循环修改部分控制条件YN先判断,后循环一、循环程序的结构形式结束初始化循环的初
xorax,ax ;被加数ax清0
movcx,100again: addax,cx ;从100,99,...,2,1倒序累加
loopagain
.modelsmall .stack256 .data sum dw? .code .startup movsum,ax ;将累加和送入指定单元 .exit0 end二、循环程序设计(例) xorax,ax ;被加数ax清0 .model例5.2在ADDR单元存放着数Y的地址,试编制一程序把Y中1的个数存入COUNT单元中开始1的个数计数器←0循环次数计数器CX←16Y左移一次CF=11的个数计数器+1CX←CX-1=0COUNT←
1的个数计数器结束NYNY
循环次数固定,完全由循环计数器控制例5.2在ADDR单元存放着数Y的地址,试编制一程序把Y中DATA SEGMENTY DW1234HADDR DWYCOUNT DB?DATA ENDSCODE SEGMENT ASSUMECS:CODE,DS:DATASTART: MOVAX,DATA MOVDS,AX MOVDL,0 MOVBX,ADDR MOVAX,[BX] MOVCX,16REPEAT: SHLAX,1 JNCNEXT INCDL NEXT:LOOPREPEAT EXIT0:MOVCOUNT,DL MOVAH,4CH INT21H CODEENDS
ENDSTART例5.2DATA SEGMENTREPEAT:开始1的个数计数器←0循环次数计数器CX←16Y左移一次CF=11的个数计数器+1CX←CX-1=0COUNT←
1的个数计数器结束NYNYY=0NY例5.2开始1的个数计数器←0循环次数计数器CX←16Y左移一次CFDATA SEGMENTY DW1234HADDR DWYCOUNTDB?DATA ENDSCODE SEGMENT ASSUMECS:CODE,DS:DATASTART:MOVAX,DATA MOVDS,AX MOVDL,0 MOVBX,ADDR MOVAX,[BX] MOVCX,16REPEAT: SHLAX,1 JNCNEXT INCDL NEXT: LOOPREPEAT EXIT0: MOVCOUNT,DL
ADDDL,30H MOVAH,2 INT21H MOVAH,4CH INT21H CODE ENDS
ENDSTARTCMPAX,0JZEXIT0例5.2JMPREPEATDATA SEGMENTREPEAT: 例5.4将正数N插入一个已升序排列的字数组的正确位置。该数组的首地址和末地址分别为ARRAY_HEAD和ARRAY_END,其中所有的数均为正数。
解法一:从数组的尾部开始比较N较大,则在比较对象后插入,结束循环N较小,则把比较对象及其后元素后移一个字循环结束的控制:执行插入操作后结束循环若N比所有元素都小,扫描整个数组后仍无法结束循环,将-1加在数组前可解决该问题
23,37,49,5232ENDHEAD-1,
23,37,49,5232,-1,例5.4将正数N插入一个已升序排列的字数组的正确位置。该数开始(ARRAY_HEAD-2)←-1初始化变址寄存器SI将N放在K的后面K<=N修改地址K后移一个字单元结束YN例5.4开始(ARRAY_HEAD-2)←-1初始化变址寄存器SI将DATAREA SEGMENT X DW?ARRAY_HEAD DW3,5,15,23,37,49ARRAY_END DW105 N DW32DATAREA ENDSPROGRAM SEGMENTMAIN PROCFARASSUMECS:PROGRAM,DS:DATAREASTART: PUSHDS SUBAX,AX PUSHAX MOVAX,DATAREA MOVDS,AX MOVAX,N MOVARRAY_HEAD-2,-1 MOVSI,0COMP:CMPARRAY_END[SI],AX JLEINSERT MOVBX,ARRAY_END[SI] MOVARRAY_END[SI+2],BX SUBSI,2 JMPCOMPINSERT: MOVARRAY_END[SI+2],AX RETMAIN ENDPPROGRAMENDS ENDSTART例5.4MOVBX,ARRAY_END[SI]CMPBX,AXJLEINSERT DATAREA SEGMENT MOVAX,例5.4将正数N插入一个已升序排列的字数组的正确位置。
该数组的首地址和末地址分别为ARRAY_HEAD和ARRAY_END,其中所有的数均为正数。
解法二:从数组的头部开始比较N较小,则在比较对象前插入,结束循环N较大,则把比较对象及其前元素前移一个字循环结束的控制:可扫描整个数组,循环次数为数组元素个数执行插入操作后结束循环若N比所有元素都小,形成新的头;若N比所有元素都大,则被置于尾部例5.4将正数N插入一个已升序排列的字数组的正确位置。该DSEG SEGMENTPARA'DATA' DW?ARRAY_HEADDW3,5,13H,23H,37H DW49H,52H,65H,78H,99H,105HCOUNT EQU($-ARRAY_HEAD)/2N DW32HDSEG ENDSCSEG SEGMENTPARA'CODE' ASSUMECS:CSEG ASSUMEDS:DSEG,SS:SSEGMAIN PROCFAR
;MAKENECCESSARYINITALIZALITION MOVAX,DSEG MOVDS,AX MOVES,AX
MOVAX,N MOVSI,0 MOVCX,COUNTREPEAT: MOVBX,ARRAY_HEAD[SI] CMPBX,AX JAEINSERT ;N较小,则转插入操作
MOVARRAY_HEAD[SI-2],BX
;数组元素前移1字单元
INCSI INCSI LOOPREPEATINSERT: MOVARRAY_HEAD[SI-2],AX
;将N加入到数组中
MOVAX,4C00H INT21HMAIN ENDP CSEG ENDS ENDMAIN;SETENTRYPOINTDSEG SEGMENTPARA'DATA' MOV例5.5设有数组X和Y,每个数组都有10个元素,完成以下计算:Z1=X1+Y1 Z2=X2+Y2 Z3=X3-Y3Z4=X4-Y4 Z5=X5-Y5 Z6=X6+Y6Z7=X7-Y7 Z8=X8-Y8 Z9=X9+Y9Z10=X10+Y10结果存入数组Z。 比例尺:0000000011011100B例5.5设有数组X和Y,每个数组都有10个元素,完成以下计DATA SEGMENTX DW11,33,10,60,4,7,19,80,45,23Y DW44,5,2,90,78,32,12,10,100,98Z DW10HDUP(?)FLAG DW0000000011011100BDATA ENDSSTK SEGMENTSTACK DW20HDUP(0)STK ENDSCODE SEGMENTASSUMECS:CODE,DS:DATA,SS:STKSTART: MOVAX,DATA MOVDS,AX
MOVBX,0 MOVCX,10 MOVDX,FLAGNEXT: MOVAX,X[BX] SHRDX,1 JCSUBTRACT ADDAX,Y[BX] JMPRESULTSUBTRACT: SUBAX,Y[BX]RESULT: MOVZ[BX],AX ADDBX,2 LOOPNEXT MOVAH,4CH INT21HCODE ENDS ENDSTARTDATA SEGMENT MOVBX,0三、多重循环程序设计 例5.7有一个首地址为A的N字数组,请编制程序使该数组中的数按照从大到小的次序整序冒泡法从第一个元素开始,依次对相邻的两个元素进行比较,使前一个元素不小于后一个元素;将所有元素比较完之后,最小的元素排到了最后;然后,除掉最后一个元素之外的元素依上述方法再进行比较,得到次小的元素排在后面;如此重复,直至完成就实现元素从大到小的排序这需要一个双重循环程序结构三、多重循环程序设计 例5.7有一个首地址为A的N字数组,冒泡法的排序序号数比较遍数1234132215316485
85321615858321685158328516158853216158冒泡法的排序序号数比较遍CSEG SEGMENTPARA‘CODE’ ASSUMECS:CSEG,DS:DSEG,SS:SSEGMAIN PROCFAR ;MAKENECCESSARYINITALIZALITION PUSHDS XORAX,AX PUSHAX MOVAX,DSEG MOVDS,AX MOVES,AX MOVCX,N DECCXLOOP1: MOVDI,CX
;保存计数器
MOVBX,0 ;数组地址指针清零LOOP2: MOVAX,A[BX] CMPAX,A[BX+2] JGECOTINUE XCHGA[BX+2],AX ;交换
MOVA[BX],AXCOTINUE: ADDBX,2 ;修改数组指针
LOOPLOOP2
MOVCX,DI ;恢复循环计数器
LOOPLOOP1 RETMAIN ENDP CSEG ENDS ENDMAIN ;SETENTRYPOINTCSEG SEGMENTPARA‘CODE’CSEG SEGMENTPARA‘CODE’ ASSUMECS:CSEG,DS:DSEG,SS:SSEGMAIN PROCFAR ;MAKENECCESSARYINITALIZALITION PUSHDS XORAX,AX PUSHAX MOVAX,DSEG MOVDS,AX MOVES,AX MOVCX,N DECCXLOOP1: MOVDI,CX
;保存计数器
MOVBX,0 ;数组地址指针清零
MOVDL,0LOOP2: MOVAX,A[BX] CMPAX,A[BX+2] JGECOTINUE XCHGA[BX+2],AX ;交换
MOVA[BX],AX
INCDL
;交换次数计数器+1COTINUE: ADDBX,2 ;修改数组指针
LOOPLOOP2
CMPDL,0 JZEXIT0
;数组已整序,则退出
MOVCX,DI
;恢复循环计数器
LOOPLOOP1
EXIT0: RETMAIN ENDP CSEG ENDS ENDMAIN ;SETENTRYPOINTCSEG SEGMENTPARA‘CODE’§5.3分支程序设计一、分支程序的结构形式二、分支程序的设计三、跳转表§5.3分支程序设计一、分支程序的结构形式AH=0fuction0NAH=1AH=2fuction1fuction2NNYYY(C)多分支结构一、分支程序的结构形式AH=0fuction0NAH=1AH分支程序的设计方法例5.9在附加段中,有一个按从小到大顺序排列的无符号数数组,其首地址存放在DI寄存器中,数组中的第一个单元存放着数组长度。在AX中有一无符号数,要求在数组中查找该数,如找到则使CF=0,并在SI中给出该元素的偏移地址;如未找到,则使CF=1。分支程序的设计方法例5.9在附加段中,有一个按从小到大顺序循环与分支程序设计课件跳跃表法例5.10试根据AL寄存器中哪一位为1(从低位到高位)把程序转移到8个不同的程序分支去。跳转目标的地址在数据段中(5-10-1.asm)跳转目标的地址在代码段中(5-10-2.asm)跳跃表法例5.10试根据AL寄存器中哪一位为1(从低位到高SSEG SEGMENTPARASTACK'STACK' DW100HDUP(0)SSEG ENDSDSEG SEGMENTPARA'DATA'TAB DWROUTINE1 ;程序段1在代码段的偏移量
DWROUTINE2 DWROUTINE3 DWROUTINE4 DWROUTINE5 DWROUTINE6 DWROUTINE7 DWROUTINE8MESS DB'THISISROUTINE'NUMBER DB8 DB0AH,0DH,'$'DSEG ENDSCSEG SEGMENTPARA'CODE' ASSUMECS:CSEG,DS:DSEG,SS:SSEGMAIN PROCFAR MOVAX,DSEG ;MAKENECCESSARYINITALIZALITION MOVDS,AX MOVES,AX
MOVAL,NUMBER
CMPAL,0 JECONTINUE_MAIN_LINE
;AL值为0则继续运行主程序段
LEABX,TABLOP1: SHRAL,1 JNCNOT_YET JMPWORDPTR[BX]NOT_YET: ADDBX,TYPETAB JMPLOP1CONTINUE_MAIN_LINE: MOVAH,4CH INT21HSSEG SEGMENTPARASTACK'STACROUTINE1: MOVNUMBER,31H JMPEXITROUTINE2: MOVNUMBER,32H JMPEXITROUTINE3: MOVNUMBER,33H JMPEXITROUTINE4: MOVNUMBER,34H JMPEXITROUTINE5: MOVNUMBER,35H JMPEXITROUTINE6: MOVNUMBER,36H JMPEXITROUTINE7: MOVNUMBER,37H JMPEXITROUTINE8: MOVNUMBER,38H JMPEXIT
EXIT: MOVDX,OFFSETMESS MOVAH,9 INT21H JMPCONTINUE_MAIN_LINE
;MOVAH,0AH ;INT21H ;RETURNDOS MOVAX,4C00H INT21HMAIN ENDPCSEG ENDS ENDMAIN;SETENTRYPOINTROUTINE1: SSEG SEGMENTPARASTACK'STACK' DW100HDUP(0)SSEG ENDSDSEG SEGMENTPARA'DATA'MESG1: DB'PLEASEINPUTTHENUMBER:$'MESS DB0AH,0DH,'THISISROUTINE'NUMBER DB? DB0AH,0DH,'$'DSEG ENDSCSEG SEGMENTPARA'CODE' ASSUMECS:CSEG,DS:DSEG,SS:SSEGMAINPROCFAR
;MAKENECCESSARYINITALIZALITION MOVAX,DSEG MOVDS,AX MOVES,AX
MOVDX,OFFSETMESG1 MOVAH,9 INT21H MOVAH,1 ;从键盘获得AL值
INT21H ANDAL,0FH DECAL ;计算表地址(号-1)*3 MOVBL,AL SHLBL,1 ADDBL,AL MOVBH,0 ADDBX,OFFSETTAB JMPBXTAB: JMPROUTINE1 JMPROUTINE2 JMPROUTINE3 JMPROUTINE4 JMPROUTINE5 JMPROUTINE6 JMPROUTINE7 JMPROUTINE8 JMPROUTINE9SSEG SEGMENTPARASTACK'STACROUTINE1: MOVNUMBER,31H JMPEXITROUTINE2: MOVNUMBER,32H JMPEXITROUTINE3: MOVNUMBER,33H JMPEXITROUTINE4: MOVNUMBER,34H JMPEXITROUTINE5: MOVNUMBER,35H JMPEXITROUTINE6: MOVNUMBER,36H JMPEXITROUTINE7: MOVNUMBER,37H JMPEXITROUTINE8: MOVNUMBER,38H JMPEXITROUTINE9: MOVNUMBER,39H JMPEXIT
EXIT: MOVDX,OFFSETMESS MOVAH,9 INT21H
;MOVAH,0AH ;INT21H ;RETURNDOS MOVAX,4C00H INT21HMAIN ENDPCSEG ENDS ENDMAIN;SETENTRYPOINTROUTINE1: 第五章循环与分支程序设计§5.1循环与转移指令§5.2循环程序设计§5.3分支程序设计第五章循环与分支程序设计§5.1循环与转移指令一、循环控制指令二、转移指令控制转移类指令通过改变IP(和CS)值,实现程序执行顺序的改变§5.1循环与转移指令一、循环控制指令控制转移类指令通过改一、循环控制指令8086指令系统的循环控制指令均为二字节指令一字节为转移的相对位移量(8位带符号的二进制数) IP←IP+相对位移量
EIP←EIP+相对位移量隐含使用CX作为循环计数器
程序中的某段需反复执行若干次时,用循环来实现短转移一、循环控制指令8086指令系统的循环控制指令均为二字节指令LOOPlabel
;CX←CX-1,CX≠0,循环到标号label一、循环控制指令LOOPE/LOOPZlabel ;CX←CX-1,CX≠0且ZF=1,循环到标号labelLOOPNE/NZlabel ;CX←CX-1,CX≠0且ZF=0,循环到标号label等于时循环不等于时循环LOOPlabel 一、循环控制指令LOOPE/L一、循环控制指令(例) MOVCX,COUNT ;设置循环次数
MOVSI,OFFSETDATA_BYTE XORAX,AX ;BX清0,用于存放累加和AGAIN: ADDAL,[SI] ADCAH,0
INCSI LOOPAGAIN ;计数器减1,不为0继续循环一、循环控制指令(例) MOVCX,COUNT ;设置循一、循环控制指令(例) MOVCX,COUNT ;设置循环次数
MOVSI,OFFSETSTRING XORBX,BX ;BX清0,用于记录空格数
MOVAL,20HAGAIN: CMPAL,[SI] JNZNEXT ;ZF=0,非空格,转移
INCBX ;ZF=1,是空格,个数加1 NEXT: INCSI LOOPAGAIN ;计数器减1,不为0继续循环一、循环控制指令(例) MOVCX,COUNT ;设置循二、转移指令无条件转移指令条件转移指令二、转移指令无条件转移指令 JMPlabel
;程序转向label标号指定的地址NEARFAR只要执行无条件转移指令JMP,就使程序转到指定的目标地址处,从目标地址处开始执行那里的指令JMP指令分成4种类型:⑴段内转移、直接寻址⑵段内转移、间接寻址⑶段间转移、直接寻址⑷段间转移、间接寻址目的地址与JMP属同一逻辑段,只修改IP值从一个代码段转移到另一个代码段,CS和IP都会被修改无条件转移指令 JMPlabel NEAR只要执行无条件转1.
无条件转移指令
—目标地址的寻址方式直接寻址方式转移地址象立即数一样,直接在指令的机器代码中,就是直接寻址方式间接寻址方式转移地址在寄存器或主存单元中,就是通过寄存器或存储器的间接寻址方式用标号表达用寄存器或存储器操作数表达1.无条件转移指令
—目标地址的寻址方式直接寻址方1.
无条件转移指令
—目标地址的范围:段内段内转移——近转移(near)在当前代码段64KB范围内转移
(±32KB范围)不需要更改CS段基值,只要改变IP偏移地址段内转移——短转移(short)转移范围可以用一个字节表达,在段内-128~+127范围的转移代码段代码段1.无条件转移指令
—目标地址的范围:段内段内转移1.无条件转移指令
—目标地址的范围:段间段间转移——远转移(far)从当前代码段跳转到另一个代码段,可以在1MB范围需要更改CS段基值和IP偏移地址目标地址必须用一个32位数表达,叫做32位远指针,它就是逻辑地址代码段代码段实际编程时,汇编程序会根据目标地址的距离,自动处理成短转移、近转移或远转移程序员可用操作符short、nearptr或farptr强制1.无条件转移指令
—目标地址的范围:段间段间转移——远段内直接寻址转移JMPlabel ;IP←IP+位移量位移量是紧接着JMP指令后的那条指令的偏移地址,到目标指令的偏移地址的地址位移当向地址增大方向转移时,位移量为正;向地址减小方向转移时,位移量为负实际为相对寻址
JMPAGAIN ;转移到AGAIN处继续执行
…… AGAIN: DECCX ;标号AGAIN的指令
……
JMPOUTPUT ;转向OUTPUT …… OUTPUT: MOVRESULT,AL ;标号OUTPUT的指令段内直接寻址转移JMPlabel ;IP←IP段内间接寻址转移JMPr16/m16 ;IP←r16/m16将一个16位寄存器或主存字单元内容送入IP寄存器,作为新的指令指针,但不修改CS寄存器的内容
JMPAX ;IP←AX JMPWORDPTR[BX] ;IP←[BX]段内间接寻址转移JMPr16/m16 ;IP←r段间直接寻址转移JMPfarptrlabel
;IP←label的偏移地址 ;CS←label的段基值将标号所在段的段基值作为新的CS值,标号在该段内的偏移地址作为新的IP值;程序跳转到新的代码段执行JMPFARPTROTHERSEG
;远转移到代码段2的otherseg段间直接寻址转移JMPfarptrlabel段间间接寻址转移JMPfarptrmem
;IP←[mem],CS←[mem+2]用一个双字存储单元表示要跳转的目标地址。这个目标地址存放在主存中连续的两个字单元中的,低位字送IP寄存器,高位字送CS寄存器MOVWORDPTR[BX],0MOVWORDPTR[BX+2],1500HJMPFARPTR[BX];转移到1500H:0段间间接寻址转移JMPfarptrmem2.条件转移指令Jcclabel
;条件满足,发生转移:IP←IP+8位位移量;条件不满足,顺序执行指定的条件cc如果成立,程序转移到由标号label指定的目标地址去执行指令;条件不成立,则程序将顺序执行下一条指令操作数label是采用短转移,称为相对寻址方式2.条件转移指令Jcclabel指定的条件cc如果成立,程2.条件转移指令Jcc指令的操作数label是一个标号一个8位位移量是相对于当前IP的,且距当前IP地址-128~+127个单元的范围之内,属于段内短距离转移Jcc指令为2个字节,条件不满足时的顺序执行就是当前指令偏移指针IP加22.条件转移指令Jcc指令的操作数label是一个标号2.条件转移指令—指令的分类Jcc指令不影响标志,但要利用标志。根据利用的标志位不同,19条指令分成4种情况:⑴判断单个标志位状态⑵比较无符号数高低⑶比较有符号数大小⑷判断计数器CX为02.条件转移指令—指令的分类Jcc指令不影响标志,但要利用助记符标志位助记符标志位JCCF=1JA/JNBECF=0且ZF=0JNCCF=0JAE/JNBCF=0或ZF=1JZ/JEZF=1JB/JNAECF=1且ZF=0JNZ/JNEZF=0JBE/JNACF=1或ZF=1JSSF=1JG/JNLESF=OF且ZF=0JNSSF=0JGE/JNLSF=OF或ZF=1JP/JPEPF=1JL/JNGESF≠OF且ZF=0JNP/JPOPF=0JLE/JNGSF≠OF或ZF=1JOOF=1JCXZCX=0JNOOF=0
实际虽然指令只有19条,但却有31个助记符
采用多个助记符,只是为了方便记忆和使用助记符标志位助记符标志位JCCF=1JA/JNBECF=0且判断单个标志位状态这组指令单独判断5个状态标志之一⑴JZ/JE和JNZ/JNE:利用零标志ZF,判断结果是否为零(或相等)⑵JS和JNS:利用符号标志SF,判断结果是正是负⑶JO和JNO:利用溢出标志OF,判断结果是否产生溢出⑷JP/JPE和JNP/JPO:利用奇偶标志PF,判断结果中“1”的个数是偶是奇⑸JC和JNC:利用进位标志CF,判断结果是否进位或借位例题例题例题例题例题
判断单个标志位状态这组指令单独判断5个状态标志之一例题例2.条件转移指令—JZ/JNZ指令 REPZCMPSB ;重复比较两个字符
JNZUNMAT
;ZF=0(不等),转移
MOVAL,0 ;顺序执行(相等)
JMPOUTPUT UNMAT: MOVAL,0FFH OUTPUT: MOVRESULT,AL
REPZCMPSB ;重复比较两个字符
JZMAT ;ZF=1(相等),转移
MOVAL,0FFH ;顺序执行(不等)
JMPOUTPUT MAT: MOVAL,0 OUTPUT: MOVRESULT,AL2.条件转移指令—JZ/JNZ指令 REPZCMPS2.条件转移指令—JS/JNS指令计算|X-Y|(绝对值)。X和Y为存放于X单元和Y单元的16位操作数,结果存入RESULT。
MOVAX,X SUBAX,Y JNSNONNEG NEGAX NONNEG: MOVRESULT,AX2.条件转移指令—JS/JNS指令计算|X-Y|(绝对值2.条件转移指令—JO/JNO指令计算X-Y。X和Y为存放于X单元和Y单元的16位操作数,若溢出,则转移到OVERFLOW处理
MOVAX,X SUBAX,Y JOOVERFLOW ... ;无溢出,结果正确OVERFLOW: ...
;有溢出处理2.条件转移指令—JO/JNO指令计算X-Y。X和Y为存放2.条件转移指令—JP/JNP指令设字符的ASCII码在AL寄存器中。将字符加上奇校验位:在字符ASCII码中为“1”的个数为奇数时令其最高位为“0”,否则令最高位为“1”
ANDAL,7FH;最高位置“0”,同时判断“1”的个数
JNPNEXT ;个数已为奇数,则转向NEXT
ORAL,80H
;否则,最高位置“1” NEXT: ...2.条件转移指令—JP/JNP指令设字符的ASCII码在A2.条件转移指令—JC/JNC指令记录BX中1的个数
XORAL,AL ;AL=0,CF=0 AGAIN: TESTBX,0FFFFH ;等价于CMPBX,0 JZNEXT SHLBX,1 JNCAGAIN INCAL JMPAGAIN NEXT: ... ;AL保存1的个数2.条件转移指令—JC/JNC指令记录BX中1的个数 2.条件转移指令
—无符号数的比较无符号数的大小用高(Above)低(Below)表示利用CF确定高低、利用ZF标志确定相等(Equal)两数的高低分成4种关系:⑴高于(不低于等于):JA
(JNBE)⑵高于等于(不低于):JAE
(JNB)⑶低于(不高于等于):JB(JNAE)⑷低于等于(不高于):JBE(JNA)2.条件转移指令
—无符号数的比较无符号数的大小用高2.
条件转移指令
—无符号数的比较(例) CMPAX,BX ;比较AX和BX JAENEXT ;若AX≥BX,转移
XCHGAX,BX ;若AX<BX,交换 NEXT: ...结果:AX保存较大的无符号数2.条件转移指令
—无符号数的比较(例) CMP2.条件转移指令
—有符号数的比较有符号数的大(Greater)小(Less)需要组合OF、SF标志,并利用ZF标志确定相等(Equal)两数的大小分成4种关系:⑴小于(不大于等于):JL(JNGE)⑵小于等于(不大于):JLE(JNG)⑶大于(不小于等于):JG
(JNLE)⑷大于等于(不小于):JGE
(JNL)2.条件转移指令
—有符号数的比较有符号数的大(G2.
条件转移指令
—有符号数的比较(例) CMPAX,BX ;比较AX和BX JGENEXT ;若AX≥BX,转移
XCHGAX,BX ;若AX<BX,交换 NEXT:...结果:AX保存较大的有符号数2.条件转移指令
—有符号数的比较(例) CMP2.
条件转移指令
—计数器CX为0转移 JCXZlabel;CX=0,发生转移:IP←IP+8位位移量;CX≠0,顺序执行CX寄存器通常在程序中用做计数器JCXZ指令用来判断计数是否为02.条件转移指令
—计数器CX为0转移 JCXZ§5.2循环程序设计一、循环程序的结构形式二、循环程序设计三、多重循环程序设计§5.2循环程序设计一、循环程序的结构形式
结束
初始化
循环的初始状态
循环体
循环的工作部分及修改部分
计数控制循环条件控制循环修改部分控制条件YN先循环,后判断一、循环程序的结构形式结束初始化循环的初一、循环程序的结构形式
结束
初始化
循环的初始状态
循环体
循环的工作部分及修改部分
计数控制循环条件控制循环修改部分控制条件YN先判断,后循环一、循环程序的结构形式结束初始化循环的初
xorax,ax ;被加数ax清0
movcx,100again: addax,cx ;从100,99,...,2,1倒序累加
loopagain
.modelsmall .stack256 .data sum dw? .code .startup movsum,ax ;将累加和送入指定单元 .exit0 end二、循环程序设计(例) xorax,ax ;被加数ax清0 .model例5.2在ADDR单元存放着数Y的地址,试编制一程序把Y中1的个数存入COUNT单元中开始1的个数计数器←0循环次数计数器CX←16Y左移一次CF=11的个数计数器+1CX←CX-1=0COUNT←
1的个数计数器结束NYNY
循环次数固定,完全由循环计数器控制例5.2在ADDR单元存放着数Y的地址,试编制一程序把Y中DATA SEGMENTY DW1234HADDR DWYCOUNT DB?DATA ENDSCODE SEGMENT ASSUMECS:CODE,DS:DATASTART: MOVAX,DATA MOVDS,AX MOVDL,0 MOVBX,ADDR MOVAX,[BX] MOVCX,16REPEAT: SHLAX,1 JNCNEXT INCDL NEXT:LOOPREPEAT EXIT0:MOVCOUNT,DL MOVAH,4CH INT21H CODEENDS
ENDSTART例5.2DATA SEGMENTREPEAT:开始1的个数计数器←0循环次数计数器CX←16Y左移一次CF=11的个数计数器+1CX←CX-1=0COUNT←
1的个数计数器结束NYNYY=0NY例5.2开始1的个数计数器←0循环次数计数器CX←16Y左移一次CFDATA SEGMENTY DW1234HADDR DWYCOUNTDB?DATA ENDSCODE SEGMENT ASSUMECS:CODE,DS:DATASTART:MOVAX,DATA MOVDS,AX MOVDL,0 MOVBX,ADDR MOVAX,[BX] MOVCX,16REPEAT: SHLAX,1 JNCNEXT INCDL NEXT: LOOPREPEAT EXIT0: MOVCOUNT,DL
ADDDL,30H MOVAH,2 INT21H MOVAH,4CH INT21H CODE ENDS
ENDSTARTCMPAX,0JZEXIT0例5.2JMPREPEATDATA SEGMENTREPEAT: 例5.4将正数N插入一个已升序排列的字数组的正确位置。该数组的首地址和末地址分别为ARRAY_HEAD和ARRAY_END,其中所有的数均为正数。
解法一:从数组的尾部开始比较N较大,则在比较对象后插入,结束循环N较小,则把比较对象及其后元素后移一个字循环结束的控制:执行插入操作后结束循环若N比所有元素都小,扫描整个数组后仍无法结束循环,将-1加在数组前可解决该问题
23,37,49,5232ENDHEAD-1,
23,37,49,5232,-1,例5.4将正数N插入一个已升序排列的字数组的正确位置。该数开始(ARRAY_HEAD-2)←-1初始化变址寄存器SI将N放在K的后面K<=N修改地址K后移一个字单元结束YN例5.4开始(ARRAY_HEAD-2)←-1初始化变址寄存器SI将DATAREA SEGMENT X DW?ARRAY_HEAD DW3,5,15,23,37,49ARRAY_END DW105 N DW32DATAREA ENDSPROGRAM SEGMENTMAIN PROCFARASSUMECS:PROGRAM,DS:DATAREASTART: PUSHDS SUBAX,AX PUSHAX MOVAX,DATAREA MOVDS,AX MOVAX,N MOVARRAY_HEAD-2,-1 MOVSI,0COMP:CMPARRAY_END[SI],AX JLEINSERT MOVBX,ARRAY_END[SI] MOVARRAY_END[SI+2],BX SUBSI,2 JMPCOMPINSERT: MOVARRAY_END[SI+2],AX RETMAIN ENDPPROGRAMENDS ENDSTART例5.4MOVBX,ARRAY_END[SI]CMPBX,AXJLEINSERT DATAREA SEGMENT MOVAX,例5.4将正数N插入一个已升序排列的字数组的正确位置。
该数组的首地址和末地址分别为ARRAY_HEAD和ARRAY_END,其中所有的数均为正数。
解法二:从数组的头部开始比较N较小,则在比较对象前插入,结束循环N较大,则把比较对象及其前元素前移一个字循环结束的控制:可扫描整个数组,循环次数为数组元素个数执行插入操作后结束循环若N比所有元素都小,形成新的头;若N比所有元素都大,则被置于尾部例5.4将正数N插入一个已升序排列的字数组的正确位置。该DSEG SEGMENTPARA'DATA' DW?ARRAY_HEADDW3,5,13H,23H,37H DW49H,52H,65H,78H,99H,105HCOUNT EQU($-ARRAY_HEAD)/2N DW32HDSEG ENDSCSEG SEGMENTPARA'CODE' ASSUMECS:CSEG ASSUMEDS:DSEG,SS:SSEGMAIN PROCFAR
;MAKENECCESSARYINITALIZALITION MOVAX,DSEG MOVDS,AX MOVES,AX
MOVAX,N MOVSI,0 MOVCX,COUNTREPEAT: MOVBX,ARRAY_HEAD[SI] CMPBX,AX JAEINSERT ;N较小,则转插入操作
MOVARRAY_HEAD[SI-2],BX
;数组元素前移1字单元
INCSI INCSI LOOPREPEATINSERT: MOVARRAY_HEAD[SI-2],AX
;将N加入到数组中
MOVAX,4C00H INT21HMAIN ENDP CSEG ENDS ENDMAIN;SETENTRYPOINTDSEG SEGMENTPARA'DATA' MOV例5.5设有数组X和Y,每个数组都有10个元素,完成以下计算:Z1=X1+Y1 Z2=X2+Y2 Z3=X3-Y3Z4=X4-Y4 Z5=X5-Y5 Z6=X6+Y6Z7=X7-Y7 Z8=X8-Y8 Z9=X9+Y9Z10=X10+Y10结果存入数组Z。 比例尺:0000000011011100B例5.5设有数组X和Y,每个数组都有10个元素,完成以下计DATA SEGMENTX DW11,33,10,60,4,7,19,80,45,23Y DW44,5,2,90,78,32,12,10,100,98Z DW10HDUP(?)FLAG DW0000000011011100BDATA ENDSSTK SEGMENTSTACK DW20HDUP(0)STK ENDSCODE SEGMENTASSUMECS:CODE,DS:DATA,SS:STKSTART: MOVAX,DATA MOVDS,AX
MOVBX,0 MOVCX,10 MOVDX,FLAGNEXT: MOVAX,X[BX] SHRDX,1 JCSUBTRACT ADDAX,Y[BX] JMPRESULTSUBTRACT: SUBAX,Y[BX]RESULT: MOVZ[BX],AX ADDBX,2 LOOPNEXT MOVAH,4CH INT21HCODE ENDS ENDSTARTDATA SEGMENT MOVBX,0三、多重循环程序设计 例5.7有一个首地址为A的N字数组,请编制程序使该数组中的数按照从大到小的次序整序冒泡法从第一个元素开始,依次对相邻的两个元素进行比较,使前一个元素不小于后一个元素;将所有元素比较完之后,最小的元素排到了最后;然后,除掉最后一个元素之外的元素依上述方法再进行比较,得到次小的元素排在后面;如此重复,直至完成就实现元素从大到小的排序这需要一个双重循环程序结构三、多重循环程序设计 例5.7有一个首地址为A的N字数组,冒泡法的排序序号数比较遍数1234132215316485
85321615858321685158328516158853216158冒泡法的排序序号数比较遍CSEG SEGMENTPARA‘CODE’ ASSUMECS:CSEG,DS:DSEG,SS:SSEGMAIN PROCFAR ;MAKENECCESSARYINITALIZALITION PUSHDS XORAX,AX PUSHAX MOVAX,DSEG MOVDS,AX MOVES,AX MOVCX,N DECCXLOOP1: MOVDI,CX
;保存计数器
MOVBX,0 ;数组地址指针清零LOOP2: MOVAX,A[BX] CMPAX,A[BX+2] JGECOTINUE XCHGA[BX+2],AX ;交换
MOVA[BX],AXCOTINUE: ADDBX,2 ;修改数组指针
LOOPLOOP2
MOVCX,DI ;恢复循环计数器
LOOPLOOP1 RETMAIN ENDP CSEG ENDS ENDMAIN ;SETENTRYPOINTCSEG SEGMENTPARA‘CODE’CSEG SEGMENTPARA‘CODE’ ASSUMECS:CSEG,DS:DSEG,SS:SSEGMAIN PROCFAR ;MAKENECCESSARYINITALIZALITION PUSHDS XORAX,AX PUSHAX MOVAX,DSEG MOVDS,AX MOVES,AX MOVCX,N DECCXLOOP1: MOVDI,CX
;保存计数器
MOVBX,0 ;数组地址指针清零
MOVDL,0LOOP2: MOVAX,A[BX] CMPAX,A[BX+2] JGECOTINUE XCHGA[BX+2],AX ;交换
MOVA[BX],AX
INCDL
;交换次数计数器+1COTINUE: ADDBX,2 ;修改数组指针
LOOPLOOP2
CMPDL,0 JZEXIT0
;数组已整序,则退出
MOVCX,DI
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 吸痰护理在危重症患者中的应用
- 基于大数据的学前儿童健康行为分析及对策研究报告
- 护理实践中的循证依据
- 护理安全评估:患者安全评估的准确性
- 医院感染监测与数据分析
- 基于大数据的智能传感器性能分析报告
- 呼吸系统疾病护理的临床案例分享
- 客户服务团队的领导力与面试技巧
- 链家房产销售顾问面试全解析
- 零售业财务主管招聘面试全攻略
- TCI 373-2024 中老年人免散瞳眼底疾病筛查规范
- 河南省中小学校本课程建设案例评选申报表
- 组织机构设置、人员配置及职责分工
- 天疱疮护理查房
- 学生心理健康一生一策档案模板
- 2024年海南省农垦投资控股集团有限公司招聘笔试参考题库含答案解析
- 高危药品管理护理课件
- 中职数学基础模块下册第8.4.1《圆的标准方程》说课课件
- 教育评价与考试改革的实践与成果培训课件
- S快递公司服务质量问题及研究对策 工商管理专业
- 水影响评价报告编制收费标准
评论
0/150
提交评论