版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
21世纪高等院校规划教材
汇编语言程序设计相伟主编
徐小平李珍香副主编中国水利水电出版社21世纪高等院校规划教材
汇编语言程序设计相伟主编
1第4章分支程序设计本章主要讲解分支程序设计的基本思想和设计方法。通过本章学习,读者应掌握以下内容:段内寻址与段间寻址无条件转移指令条件转移指令二分支程序设计方法多分支程序设计方法第4章分支程序设计本章主要讲解分支程序设计的基本思想和设24.1转移地址的寻址方式Intel8086/8088CPU中,程序的执行顺序是由代码段寄存器CS和指令指针IP确定的。CS包含当前指令所在代码段的段地址,IP则是要执行的下一条指令的偏移地址。通常情况下,程序是顺序执行的,即CPU取出指令后,自动形成下一条指令的地址,依指令序列顺序执行。但有时需要改变程序的流程,这就要给出目标指令的段地址(CS)和偏移地址(IP)值,这就是与转移地址有关的寻址方式。与转移地址有关的寻址方式有四种:段内直接寻址、段内间接寻址、段间直接寻址和段间间接寻址。4.1转移地址的寻址方式Intel8086/8088C34.1.1段内寻址段内寻址分为段内直接寻址和段内间接寻址两种方式。其转移方式是在当前代码段64KB范围内转移,因此不需要更改段地址CS的值,只要改变偏移地址IP的值即可。4.1.1段内寻址段内寻址分为段内直接寻址和段内间接寻址41.段内直接寻址指令中直接给出转移地址的偏移量(8位或16位),转移目标与转移指令在同一段内。转移指令执行后,CS值保持不变。转移的有效地址为当前的IP值与指令中指定的偏移量之和。即目标地址=IP(当前值)+偏移量其中偏移量为8位或16位有符号数。若偏移量为正数,向前转移(即高地址方向);若偏移量为负数,则向后转移(即低地址方向)。另外,对8位偏移量,其转移范围为-128~+127,称为短转移;对16位偏移量,其转移范围为-32768~+32767,称为近转移。短转移指令为2字节指令,IP的当前值为转移指令所在的IP值加2。近转移指令为3字节指令,IP的当前值为转移指令所在的IP值加3。1.段内直接寻址指令中直接给出转移地址的偏移量(8位或16位5例4-1:分析下列指令。JMPSHORTDSP1;短转移指令JMPNEARPTRDSP2;近转移指令假设两条指令存放地址均为1000H:0200H,偏移量DSP1为08H,偏移量DSP2为0012H。短转移指令执行时,当前IP值=0200H+2=0202H。目标地址=IP(当前值)+偏移量=0202H+08H=020AH指令执行后将转向1000H:020AH去执行。近转移指令执行时,当前IP值=0200H+3=0203H。目标地址=IP(当前值)+偏移量=0203H+0012H=0215H指令执行后将转向1000H:0215H去执行。例4-1:分析下列指令。JMPSHORTD62.段内间接寻址与段内直接寻址方式相同,转移目标与转移指令在同一段内。转移指令执行后,CS值保持不变。与段内直接寻址方式不同的是,转移的有效地址值存放在16位的通用寄存器或连续两个存储单元中。若有效地址在存储单元中,一定要指出存储单元为字型。2.段内间接寻址与段内直接寻址方式相同,转移目标与转移指令在7例4-2:假设(DS)=2000H,(BX)=3000H,(23000H)=2536H,分析下列指令。JMPBX
指令执行后,将BX的内容直接赋给IP。所以,(IP)=3000H。JMPWORDPTR[BX]指令执行后,先计算出存储单元地址23000H,再从该单元中取出内容送给IP。所以,(IP)=2536H。例4-2:假设(DS)=2000H,(BX)=3000H,(84.1.2段间寻址段间寻址分为段间直接寻址和段间间接寻址两种方式。其转移方式是从当前代码段跳转到另一个代码段,因此需要修改CS段地址和IP偏移地址的值。4.1.2段间寻址段间寻址分为段间直接寻址和段间间接寻91.段间直接寻址在指令中直接给出了转移目标的段地址和偏移地址。只要用指令中指定的偏移地址代替IP寄存器的内容,用指令中指定的段地址代替段寄存器CS的内容就可以完成从一个段到另一个段的转移操作。段间直接转移通常叫远转移(farjump),指令的操作数必须附加FARPTR操作符。1.段间直接寻址在指令中直接给出了转移目标的段地址和偏移地址10例4-3:执行如下指令JMPFARPTRDSP假设指令存放地址为1000H:0200H,
DSP的有效地址为3620H,段地址
为2000H。则指令执行后,(IP)=3620H,(CS)=2000H。
程序转移到2000H:3620H处继续执行。例4-3:执行如下指令JMPFARPTR112.段间间接寻址与段间直接寻址方式相同,转移目标与转移指令不在同一段内,转移指令执行后,CS和IP都发生变化。不同的是转移目标的偏移地址和段地址存储在两个连续的字存储单元中。因此指令中需要用DWORDPTR操作符将存储单元指定为双字单元。指令执行时,根据存储单元的寻址方式计算出存储单元地址,从该存储单元取第一个字传送到IP,取第二个字传送到CS,这样就可以实现段间转移。2.段间间接寻址与段间直接寻址方式相同,转移目标与转移指令不12例4-4:执行如下指令JMPDWORDPTR6[BX]假设:(CS)=1000H,(IP)=0600H,(DS)=2000H,(BX)=1000H,(21006H)=3000H,(21008H)=6000H。则指令执行后,(CS)=6000H,(IP)=3000H。程序转移到6000H:3000H处继续执行。例4-4:执行如下指令JMPDWORDPTR134.2无条件转移指令无条件转移指令JMP使CPU无条件地转移到指令中指明的目的地址处执行。它不能构成分支程序,但在分支程序中却往往需要用它将各分支的出口重新汇集到一起。特别是当条件转移指令的转移范围超过-128~+127个字节时,往往要借助无条件转移指令实现预定的转移。转移可分成两类:段内转移和段间转移。段内转移是指在同一代码段内进行转移,此时只需改变IP寄存器的内容,即用新的转移目标地址代替原有的IP值就可达到转移的目的。段间转移则是要转到另一个段去执行程序,此时不仅要修改IP寄存器的内容,还需要修改CS寄存器的内容才能达到目的。因此,此时的转移目标地址应该由新的段地址和偏移地址两部分组成。4.2无条件转移指令无条件转移指令JMP使CPU无条件地144.2.1段内无条件转移1.段内直接转移指令格式:①JMP标号;IP←(IP)+位移量②JMPSHORT标号;IP←(IP)+8位位移量,短转移③JMPNEARPTR标号;IP←(IP)+16位位移量,近转移功能:无条件地转移到指令指定的标号处,执行从该标号开始的指令。其中:JMP为指令操作码。标号为8位或16位偏移量。4.2.1段内无条件转移1.段内直接转移152.段内间接转移指令格式:①JMP寄存器②JMPWORDPTR存储单元功能:程序转移的有效地址放在寄存器或存储单元中,执行指令时,将寄存器或字存储单元中的有效地址写入IP,从而实现转移。2.段内间接转移指令格式:164.2.2段间无条件转移1.段间直接转移指令格式:
①JMP标号②JMPFARPTR标号功能:无条件地转移到另一个代码段的标号处,执行从该标号开始的指令。标号所在段的段地址作为新的CS,标号在该段内的偏移地址作为新的IP。4.2.2段间无条件转移1.段间直接转移172.段间间接转移指令格式:JMPDWORDPTR存储单元功能:指令执行时,从指定存储单元连续取出两个字,第一个字送给IP,第二个字送给CS,从而实现段间转移。JMP指令不影响状态标志位。2.段间间接转移指令格式:184.3条件转移指令条件转移指令根据上一条指令所设置的条件标志作判断依据,条件满足则程序转移,否则顺序执行。这类转移指令的转移均属于短转移,即转移目标地址距当前IP所表示的地址的距离为-128~+127字节。语句格式为:助记符标号条件转移指令共有18条,可分成以下三类:①简单条件转移指令。②无符号数条件转移指令。③有符号数条件转移指令。条件转移指令均不影响状态标志位。4.3条件转移指令条件转移指令根据上一条指令所设置的条件194.3.1简单条件转移指令简单条件转移指令共有10条指令。它们是根据5个标志位CF、ZF、SF、OF、PF的两种状态(1或0)而设置的。一般适用于测试某一次运算结果的状态,并根据不同的状态标志产生不同的分支进行处理。下面分别举例说明。4.3.1简单条件转移指令简单条件转移指令共有10条指令20例4-5:假设AX中为一带符号数,求AX中数的绝对值。分析:求一个数的绝对值时,首先要测试该数的正负。我们可以测试其最高位,也可以测试符号标志。因此以下两个程序段均可求出AX中数的绝对值。程序段1:TESTAX,8000HJZNEXT;测试AX最高位,为零该数为正,转到NEXTNEGAX;否则,AX为负,求补运算NEXT:…………程序段2:ANDAX,AX;影响标志位JNSNEXT;测试AX的符号位,为正则转到NEXTNEGAX;否则,AX为负,求补运算NEXT:…………例4-5:假设AX中为一带符号数,求AX中数的绝对值。分析:21例4-6:计算X+Y,X和Y单元分别存放着一个16位有符号数。若结果有溢出,则转移到OVERFLOW处理。分析:两个有符号数相加,影响OF的值。若OF置1,则产生溢出。程序段如下:MOVAX,XADDAX,YJOOVERFLOW……;没有溢出,结果正确OVERFLOW:……;溢出处理例4-6:计算X+Y,X和Y单元分别存放着一个16位有符号数22例4-7:统计寄存器BX中1的个数。分析:要统计寄存器BX中1的个数,可以通过移位指令将BX中的每一位依次移入CF中,若CF=1则CL的值加1。这样就可以统计出BX中1的个数。程序段如下:MOVCL,0;保存BX中1的个数,初值为0AGAIN:ANDBX,BXJZEXIT,(BX)=0时,结束循环转EXITSALBX,1;将BX中的最高位移入CF中JNCAGAIN;如果CF=0转AGAININCCL;否则,CL的值加1JMPAGAIN;转AGAIN处继续处理EXIT:……
例4-7:统计寄存器BX中1的个数。分析:要统计寄存器BX中234.3.2无符号数条件转移指令这类指令往往跟在比较指令之后,视比较对象为无符号数。根据比较结果的不同状态,设置了高于(A-Above)、高于或等于(AE-AboveorEqual)、低于(B-Below)、低于或等于(BE-BeloworEqual)四条指令。4.3.2无符号数条件转移指令这类指令往往跟在比较指令之24无符号数条件转移指令①JA/JNBE用于两个无符号数a、b的比较,若a>b则条件满足,实现转移。②JNA/JBE用于两个无符号数a、b的比较,若a≤b则条件满足,实现转移。③JB/JNAE用于两个无符号数a、b的比较,若a<b则条件满足,实现转移。④JNB/JAE用于两个无符号数a、b的比较,若a≥b则条件满足,实现转移。四条指令的共同点是根据两个无符号数比较的结果,判断CF、ZF的状态是否满足转移条件,当满足条件时转移,否则顺序执行。适用于地址比较、循环次数比较或双精度数的低位字的比较等。无符号数条件转移指令①JA/JNBE25例4-8:阅读下面程序段,若寄存器AL的值分别取20H、5、0FFH和2,分析程序段的执行情况。程序段如下:CMPAL,5JANEXTADDAL,5NEXT:……分析:本程序段使用了无符号数跳转指令JA,若(AL)>5则转NEXT,否则顺序执行。(1)(AL)=20H>5,满足条件,跳至NEXT处执行。(2)(AL)=5,不满足条件,顺序执行“ADDAL,5”。(3)(AL)=0FFH,由于JA是无符号数跳转指令,对无符号数来说(AL)=0FFH>5,满足转移条件,故跳转至NEXT处执行。(4)(AL)=2<5,不满足条件,故顺序执行后继指令。例4-8:阅读下面程序段,若寄存器AL的值分别取20H、5、26例4-9:分析以下程序段:MOVSI,0;SI←0JP:MOVWORDPTR[SI],0;[SI]←0ADDSI,2;SI←(SI)+2CMPSI,0F000H;判断(SI)是否小于等于0F000HJNAJP;若小于等于,则转JP执行……分析:该程序段的功能是将当前数据段中偏移地址为0~0F000H的全部字存储单元清0,其中SI为送数指针。注意:在比较判断(SI)是否小于等于0F000H时,由于地址是无符号数,所以必须选用无符号数条件转移指令JNA,才能完成预定功能。例4-9:分析以下程序段:MOVSI,274.3.3带符号数条件转移指令在程序设计中,有时需要把处理对象视为带符号数(补码表示)。当比较两个带符号数的大小时,要选用带符号数条件转移指令。带符号数条件转移指令是根据条件标志ZF、SF、OF的特定组合来决定是否转移,共设置了大于、大于或等于、小于、小于或等于四条指令。4.3.3带符号数条件转移指令在程序设计中,有时需要把处28带符号数条件转移指令①JG/JNLE用于两个有符号数a、b比较。若a>b,即符号标志SF与溢出标志OF具有相同状态(SF=OF)且零标志ZF=0时,条件满足,实现转移。②JNG/JLE用于两个有符号数a、b的比较。若a≤b,即当SF≠OF或ZF=1时,条件满足,实现转移。③JL/JNGE用于两个有符号数a、b的比较。若a<b,即当SF≠OF时,条件满足,实现转移。④JNL/JGE用于两个有符号数a、b的比较。若a≥b,即当SF=OF时,条件满足,实现转移。四条指令的共同点是根据两个带符号数比较运算的结果,组合SF、OF标志,并利用ZF标志确定转移与否。下面举例说明条件转移指令的使用方法。带符号数条件转移指令①JG/JNLE29例4-10:假设有两个双精度数a和b,分别存储在AX、BX和CX、DX中,分析下列程序段的功能。程序段如下:CMPAX,CXJGUPPERJLLOWERCMPBX,DXJAUPPERLOWER:……UPPER:……图4-4
比较两个数大小算法流程图(AX)>(CX)(AX)<(CX)(BX)>(DX)NNNYYY标号UPPER处标号LOWER处分析:本程序段的功能是比较两个双精度数a和b的大小,若a﹥b则转向UPPER执行,否则转向LOWER执行。程序段流程图如图4-4所示。例4-10:假设有两个双精度数a和b,分别存储在AX、BX和30例4-11:将例4-9程序段中的JNA指令改成JNG指令,分析程序段功能。程序段如下:MOVSI,0;SI←0JP:MOVWORDPTR[SI],0;[SI]←0ADDSI,2;SI←(SI)+2CMPSI,0F000H;判断(SI)是否小于等于0F000HJNGJP;若小于等于,则转JP执行……例4-11:将例4-9程序段中的JNA指令改成JNG指令,分31分析:该程序段在进行比较判断时,选用了带符号数条件转移指令JNG。在第一次执行比较指令“CMPSI,0F000H”时,(SI)=2,它与带符号数0F000H(即-1000H)比较,显然2>-1000H,不满足“JNG”的转移条件而顺序执行后继语句。这样就只能将0送入偏移地址为0的字单元中,无法实现将当前数据段中偏移地址为0~0F000H的全部字存储单元清0。以上例子说明在设计分支程序时一定要注意正确选择条件转移指令。分析:该程序段在进行比较判断时,选用了带符号数条件转移指令J324.4分支程序设计方法在实际应用中,计算机处理的问题不可能全是顺序地执行操作,而往往需要对出现的各种情况进行分析判断,以决定进行不同的处理。这种分不同情况进行不同处理的程序结构就是分支程序结构。分支程序结构有两种形式,如图4-5所示:图4-5
分支程序结构示意图图(a)二分支结构判定条件为真NY分支1分支2图(b)多分支结构判定条件条件1分支2分支1分支n……条件2条件n不论哪一种形式,它们的共同特点是:运行方向是向前的,在某一种确定条件下,只能执行多个分支中的一个分支。4.4分支程序设计方法在实际应用中,计算机处理的问题不可334.4.1二分支程序设计所谓二分支程序设计,就是根据判定条件为真或为假,从两条分支中选择一条分支去执行。二分支程序中的一种特殊情况就是只有一个分支程序段,另一个分支是顺序执行,有时也把这种结构称为单分支结构。4.4.1二分支程序设计所谓二分支程序设计,就是根据判定34例4-12:分析下列程序段的结构。CMPAX,0JGEDONE;如果(AX)≥0,则转DONENEGAX;否则进行求补运算DONE:MOVRESULT,AX;保存结果……图4-6
单分支程序结构示意图(AX)≥0为真YYAX←-(AX)RESULT←(AX)N本程序段用来计算AX中带符号数的绝对值,是一个典型的单分支结构。程序段流程图如图4-6所示:例4-12:分析下列程序段的结构。CM35要设计双分支程序结构,首先要产生条件,然后对产生的条件进行分析判断,根据判断结果决定执行哪一个分支,最后转入相应程序段的起始地址去执行分支程序。其中产生条件的指令通常由指令系统中影响状态标志位的指令来产生,如算术运算指令(如ADD、SUB、CMP)、逻辑运算指令(如AND、TEST)、移位指令(如SHR、SHL)等等。要想用好这些指令,就要搞清楚这些指令的功能及其对标志位的影响。特别是要熟练掌握状态标志位CF、ZF、PF、SF和OF的含义。下面我们通过例子来介绍二分支程序设计方法。要设计双分支程序结构,首先要产生条件,然后对产生的条件进行分36例4-13:从键盘输入0~9中任一自然数x,求其立方值。若输入的字符不是0~9中的某数字,则显示“INPUTERROR!”,表明输入错误。分析:求一个数的立方值可以用乘法运算实现,也可以构造一立方表,通过查表实现。此处用查表法,查表法执行速度比较快。输入数据为0至9中任一自然数,用一字节单元存放其值;输出数据是该数的立方值,用一字单元存放其值。若输入时不慎按下0~9之外的字符键,则显示错误提示信息。存储单元和寄存器分配如下:字节变量X中存放键入的自然数x。字变量Y中存放x的立方值。AX是用来存放立方值的工作单元。BX是用来进行查表的工作单元。例4-13:从键盘输入0~9中任一自然数x,求其立方值。37图4-8
求立方值程序流程图(AL)是0~9中某一数字符Y将字符ASCII码转换成数字真值Y←求立方值N开始结束AL←从键盘输入字符显示错误提示信息假定立方表的首地址为TAB,表中共10项,每项占一个字,用来存放x的立方值。从表的结构可知,x的立方值在表中的存放地址与x有如下对应关系:(TAB+2*x)=x的立方值对于每个键入的x,从字单元TAB+2*x中取出的数据便是其立方值。从键盘接受数字输入使用1号系统功能调用,此时送入AL中的是x的ASCII码,而不是x的真值。所以要首先将x的ASCII码转换成x的真值,然后用TAB+2*x计算x立方值的存放地址,按此地址查到x的立方值。程序流程图如图4-8所示:图4-8求立方值程序流程图(AL)是0~9中某一数字符Y将38源程序如下:STACKSEGMENTSTACKDB200DUP(0)STACKENDSDATASEGMENTINPUTDB‘PLEASEINPUTX(0..9):$’TABDW0,1,8,27,64,125,216,343,512,729XDB?Y DW?INERRDB0DH,0AH,’INPUTERROR!$’DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXLEADX,INPUTMOVAH,9INT21H;9号调用显示提示信息MOVAH,1INT21H;AL←1号调用从键盘接受一字符输入源程序如下:STACKSEGMENTSTACK39CMPAL,‘0’;若输入字符不是0~9中的某一数字,转LERRJBLERRCMPAL,‘9’JALERRANDAL,0FHMOVX,AL;X←x的真值ADDAL,ALMOVBL,AL;BX←2﹡xMOVBH,0MOVAX,TAB[BX]MOVY,AX;Y←x的立方值EXIT:MOVAH,4CHINT21H;结束程序,返回DOS状态LERR:MOVDX,OFFSETINERRMOVAH,9;显示错误提示信息INT21HJMPEXITCODEENDSENDBEGIN程序运行时,屏幕首先显示“PLEASEINPUTX(0..9):”,若键入2,则2*x=4,4→BX,从字单元TAB+4中取出2的立方值8送入Y中。若键入字符‘a’,因其不是‘0’~‘9’中的某一数字符,故显示“INPUTERROR!”。CMPAL,‘0’;若输入40例4-14:将a、b、c三个十六位无符号数分别与零比较,如果三个数均不为零,求出三个数之和存放在变量d中(假设总和小于65535),若其中至少有一个数为零,则显示“ERROR!”。分析:本题目的程序结构属于双分支结构的嵌套形式,对标志位的判断需要进行两次以上,才能确定其分支。程序流程图如图4-9所示。存储单元和寄存器分配如下:字变量A、B、C用来存放三个十六位无符号数;变量D用来存放三个数的和;AX是用来求和的工作单元。图4-9
求三个数和的程序流程图A=0YD←求三数和N开始结束显示”ERROR!”B=0C=0NNYY例4-14:将a、b、c三个十六位无符号数分别与零比较,如果41源程序如下:STACKSEGMENTSTACKDB200DUP(0)STACKENDSDATASEGMENTADW1234HBDW5678HCDW3562HDDW?INERRDB0DH,0AH,’ERROR!$’DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXMOVAX,0;AX清0CMPA,0JZNEXT;a=0,转NEXTCMPB,0JZNEXT;b=0,转NEXT源程序如下:STACKSEGMENTSTACK42CMPC,0JZNEXT;c=0,转NEXTADDAX,AADDAX,BADDAX,CMOVD,AX;三数求和,结果存入D中JMPEXITNEXT:MOVDX,OFFSETINERRMOVAH,9INT21HEXIT:MOVAH,4CHINT21H;结束程序,返回DOS状态CODEENDSENDBEGIN本程序运行时,由于A、B、C三个数均不为零,故求出三个数之和9E0EH存放在变量D中。读者可任意修改A、B、C三个变量的值,比较其运行结果。CMPC,043例4-16:假设有三个单字节无符号数依次存放在BUF1开始的存储区中,试编写程序将它们从大到小排列并依次存放在BUF2开始的存储区中。分析(方法一)∶将三个无符号数依次送入AL、BL、CL三个工作单元中,然后在三个工作单元之间比较大小,排好顺序后依次存放在BUF2开始的存储区中。程序流程图如图4-11所示:存储单元和寄存器分配如下:BUF1用来保存原始数据的存储区首址;BUF2用来存放已排序数据的存储区首址;AL、BL、CL用来存放原始数据的工作单元;SI用来指向BUF1的工作指针DI用来指向BUF2的工作指针。例4-16:假设有三个单字节无符号数依次存放在BUF1开始的44图4-11
将三个数由大到小排列程序流程图(AL)≥(BL)YN开始结束NYAL、BL、CLNN将三个数分别送到AL、BL、CL中(BL)≥(CL)(BL)≥(CL)(AL)≥(CL)(AL)≥(CL)AL、CL、BLCL、AL、BLCL、BL、ALBL、AL、CLBL、CL、ALYYYN源程序如下:STACKSEGMENTSTACKDB200DUP(0)STACKENDSDATASEGMENTBUF1DB56H,12H,78HBUF2DB3DUP(0)DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXMOVSI,OFFSETBUF1;SI指向BUF1存储区MOVDI,OFFSETBUF2;DI指向BUF2存储区MOVAL,[SI]MOVBL,[SI+1];将原始数据分别送入AL、BL、CLMOVCL,[SI+2]CMPAL,BLJAENEXT1CMPBL,CL图4-11将三个数由大到小排列程序流程图(AL)≥(BL)45JAENEXT3MOV[DI],CLMOV[DI+1],BLMOV[DI+2],ALJMPEXITNEXT1:CMPBL,CLJAENEXT2CMPAL,CLJAENEXT21MOV[DI],CLMOV[DI+1],ALMOV[DI+2],BLJMPEXITNEXT2:MOV[DI],ALMOV[DI+1],BLMOV[DI+2],CLJMPEXITNEXT21:MOV[DI],ALMOV[DI+1],CLMOV[DI+2],BLJMPEXITNEXT3:CMPAL,CLJAENEXT31MOV[DI],BLMOV[DI+1],CLMOV[DI+2],ALJMPEXITNEXT31:MOV[DI],BLMOV[DI+1],ALMOV[DI+2],CLEXIT:MOVAH,4CHINT21HCODEENDSENDBEGIN程序运行后,BUF2存储区中依次存储78H56H12H。JAENEXT346由图4-11可以看到,用此种方法来比较三个数的大小是非常麻烦的,编程工作量很大。下面我们再来介绍一种简单方法。由图4-11可以看到,用此种方法来比较三个数的大小是非常麻烦47(方法二):首先将三个无符号数依次送入AL、BL、CL三个工作单元中,然后比较AL和BL,若AL小于BL,则将两者内容交换;再比较AL和CL,若AL小于CL,将两者内容交换,这样AL中保存的就是三个数中的最大者。再比较BL与CL,若BL小于CL,就将两者内容交换,即将最小的数放在CL中。最终将三个数按由大到小的顺序依次存放在AL、BL和CL中。程序流程图如图4-12所示:存储单元和寄存器分配同方法一。源程序如下:Y开始结束N将三个数分别送到AL、BL、CL中图4-12
将三个数由大到小排列程序流程图(AL)≥(BL)(AL)和(BL)交换(AL)≥(CL)按AL、BL、CL顺序依次存回N(AL)和(CL)交换N(BL)和(CL)交换(BL)≥(CL)YY(方法二):首先将三个无符号数依次送入AL、BL、CL三个工48STACKSEGMENTSTACKDB200DUP(0)STACKENDSDATASEGMENTBUF1DB56H,12H,78HBUF2DB3DUP(0)DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXMOVSI,OFFSETBUF1MOVDI,OFFSETBUF2MOVAL,[SI]MOVBL,[SI+1]MOVCL,[SI+2]CMPAL,BLJAENEXT1XCHGAL,BLNEXT1:CMPAL,CLJAENEXT2XCHGAL,CLNEXT2:CMPBL,CLJAENEXT3XCHGBL,CLNEXT3:MOV[DI],ALMOV[DI+1],BLMOV[DI+2],CLMOVAH,4CHINT21HCODEENDSENDBEGIN读者可对照流程图自己分析源程序。显然第二种方法比较次数更少,编程工作量也大大减少。STACKSEGMENTSTACK494.4.2多分支程序设计在实际应用中,有时会碰到多分支程序结构。多分支程序结构相当于一个多路开关,有多个并行的分支程序段,每个分支程序段与一个条件相对应,执行时只能执行其中一个分支段。若用条件转移语句实现,则N条分支需要N-1个条件转移指令完成,转移速度慢,程序代码长。因此常采用地址表法来实现。地址表法的设计思想是:在程序段中开辟一些存储空间,形成一张地址表,用于依次存放各分支程序段的程序入口地址。程序执行时,首先判断出满足某分支程序段的条件,由此求出该分支程序段的编号。该编号乘2(段内转移),或乘4(段间转移)得到相对地址表的偏移量,再加上地址表首地址,即得到地址表中的一个地址。在这个地址表地址中存放着分支程序段的偏移地址(或偏移地址+段地址),转到该地址去执行程序,即执行该分支程序段。4.4.2多分支程序设计在实际应用中,有时会碰到多分支程50例4-17:设计一个程序,根据键盘输入的1~9数字转向9个不同的处理程序段。分析:在数据段定义一个存储区,形成一地址表,用来存放9个处理程序段的起始地址。将键盘输入的1~9数字符转换为真值,用于查表得到偏移地址。若输入非法字符则提示出错。程序流程图如图4-13所示:源程序如下:STACKSEGMENTSTACKDB200DUP(0)STACKENDS图4-13
多分支结构程序流程图是数字字符?1计算转移地址,转向P02计算转移地址,转向P01计算转移地址,转向P09……29Y开始结束显示错误提示信息AL←从键盘输入一个字符数字=?N例4-17:设计一个程序,根据键盘输入的1~9数字转向951CODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXLEADX,INPUTMOVAH,9INT21H;9号调用显示提示信息MOVAH,1INT21H;1号调用从键盘接受一字符输入CMPAL,‘1’;若输入字符不是1~9中的某一数字,转LERR
JBLERRCMPAL,‘9’JALERR ANDAX,000FH;将ASCII码转换成数字DECAXADDAX,AXMOVBX,AXJMPTAB[BX];查表,段内间接转移EXIT:MOVAH,4CHINT21HLERR:MOVDX,OFFSETINERRMOVAH,9INT21HJMPEXITP01:……;各处理程序入口P02:………………P09:……CODEENDSENDBEGINCODESEGMENT52本章小结本章主要介绍了与转移有关的寻址方式、转移指令,以及分支程序设计的基本思想和设计方法。通过本章的学习,一定要熟练掌握无条件转移指令和条件转移指令,正确理解转移指令的功能和使用条件,分清无符号数的条件转移指令和带符号数的条件转移指令的区别,熟练掌握分支程序设计。本章小结本章主要介绍了与转移有关的寻址方式、转移指令,以及分5321世纪高等院校规划教材
汇编语言程序设计相伟主编
徐小平李珍香副主编中国水利水电出版社21世纪高等院校规划教材
汇编语言程序设计相伟主编
54第4章分支程序设计本章主要讲解分支程序设计的基本思想和设计方法。通过本章学习,读者应掌握以下内容:段内寻址与段间寻址无条件转移指令条件转移指令二分支程序设计方法多分支程序设计方法第4章分支程序设计本章主要讲解分支程序设计的基本思想和设554.1转移地址的寻址方式Intel8086/8088CPU中,程序的执行顺序是由代码段寄存器CS和指令指针IP确定的。CS包含当前指令所在代码段的段地址,IP则是要执行的下一条指令的偏移地址。通常情况下,程序是顺序执行的,即CPU取出指令后,自动形成下一条指令的地址,依指令序列顺序执行。但有时需要改变程序的流程,这就要给出目标指令的段地址(CS)和偏移地址(IP)值,这就是与转移地址有关的寻址方式。与转移地址有关的寻址方式有四种:段内直接寻址、段内间接寻址、段间直接寻址和段间间接寻址。4.1转移地址的寻址方式Intel8086/8088C564.1.1段内寻址段内寻址分为段内直接寻址和段内间接寻址两种方式。其转移方式是在当前代码段64KB范围内转移,因此不需要更改段地址CS的值,只要改变偏移地址IP的值即可。4.1.1段内寻址段内寻址分为段内直接寻址和段内间接寻址571.段内直接寻址指令中直接给出转移地址的偏移量(8位或16位),转移目标与转移指令在同一段内。转移指令执行后,CS值保持不变。转移的有效地址为当前的IP值与指令中指定的偏移量之和。即目标地址=IP(当前值)+偏移量其中偏移量为8位或16位有符号数。若偏移量为正数,向前转移(即高地址方向);若偏移量为负数,则向后转移(即低地址方向)。另外,对8位偏移量,其转移范围为-128~+127,称为短转移;对16位偏移量,其转移范围为-32768~+32767,称为近转移。短转移指令为2字节指令,IP的当前值为转移指令所在的IP值加2。近转移指令为3字节指令,IP的当前值为转移指令所在的IP值加3。1.段内直接寻址指令中直接给出转移地址的偏移量(8位或16位58例4-1:分析下列指令。JMPSHORTDSP1;短转移指令JMPNEARPTRDSP2;近转移指令假设两条指令存放地址均为1000H:0200H,偏移量DSP1为08H,偏移量DSP2为0012H。短转移指令执行时,当前IP值=0200H+2=0202H。目标地址=IP(当前值)+偏移量=0202H+08H=020AH指令执行后将转向1000H:020AH去执行。近转移指令执行时,当前IP值=0200H+3=0203H。目标地址=IP(当前值)+偏移量=0203H+0012H=0215H指令执行后将转向1000H:0215H去执行。例4-1:分析下列指令。JMPSHORTD592.段内间接寻址与段内直接寻址方式相同,转移目标与转移指令在同一段内。转移指令执行后,CS值保持不变。与段内直接寻址方式不同的是,转移的有效地址值存放在16位的通用寄存器或连续两个存储单元中。若有效地址在存储单元中,一定要指出存储单元为字型。2.段内间接寻址与段内直接寻址方式相同,转移目标与转移指令在60例4-2:假设(DS)=2000H,(BX)=3000H,(23000H)=2536H,分析下列指令。JMPBX
指令执行后,将BX的内容直接赋给IP。所以,(IP)=3000H。JMPWORDPTR[BX]指令执行后,先计算出存储单元地址23000H,再从该单元中取出内容送给IP。所以,(IP)=2536H。例4-2:假设(DS)=2000H,(BX)=3000H,(614.1.2段间寻址段间寻址分为段间直接寻址和段间间接寻址两种方式。其转移方式是从当前代码段跳转到另一个代码段,因此需要修改CS段地址和IP偏移地址的值。4.1.2段间寻址段间寻址分为段间直接寻址和段间间接寻621.段间直接寻址在指令中直接给出了转移目标的段地址和偏移地址。只要用指令中指定的偏移地址代替IP寄存器的内容,用指令中指定的段地址代替段寄存器CS的内容就可以完成从一个段到另一个段的转移操作。段间直接转移通常叫远转移(farjump),指令的操作数必须附加FARPTR操作符。1.段间直接寻址在指令中直接给出了转移目标的段地址和偏移地址63例4-3:执行如下指令JMPFARPTRDSP假设指令存放地址为1000H:0200H,
DSP的有效地址为3620H,段地址
为2000H。则指令执行后,(IP)=3620H,(CS)=2000H。
程序转移到2000H:3620H处继续执行。例4-3:执行如下指令JMPFARPTR642.段间间接寻址与段间直接寻址方式相同,转移目标与转移指令不在同一段内,转移指令执行后,CS和IP都发生变化。不同的是转移目标的偏移地址和段地址存储在两个连续的字存储单元中。因此指令中需要用DWORDPTR操作符将存储单元指定为双字单元。指令执行时,根据存储单元的寻址方式计算出存储单元地址,从该存储单元取第一个字传送到IP,取第二个字传送到CS,这样就可以实现段间转移。2.段间间接寻址与段间直接寻址方式相同,转移目标与转移指令不65例4-4:执行如下指令JMPDWORDPTR6[BX]假设:(CS)=1000H,(IP)=0600H,(DS)=2000H,(BX)=1000H,(21006H)=3000H,(21008H)=6000H。则指令执行后,(CS)=6000H,(IP)=3000H。程序转移到6000H:3000H处继续执行。例4-4:执行如下指令JMPDWORDPTR664.2无条件转移指令无条件转移指令JMP使CPU无条件地转移到指令中指明的目的地址处执行。它不能构成分支程序,但在分支程序中却往往需要用它将各分支的出口重新汇集到一起。特别是当条件转移指令的转移范围超过-128~+127个字节时,往往要借助无条件转移指令实现预定的转移。转移可分成两类:段内转移和段间转移。段内转移是指在同一代码段内进行转移,此时只需改变IP寄存器的内容,即用新的转移目标地址代替原有的IP值就可达到转移的目的。段间转移则是要转到另一个段去执行程序,此时不仅要修改IP寄存器的内容,还需要修改CS寄存器的内容才能达到目的。因此,此时的转移目标地址应该由新的段地址和偏移地址两部分组成。4.2无条件转移指令无条件转移指令JMP使CPU无条件地674.2.1段内无条件转移1.段内直接转移指令格式:①JMP标号;IP←(IP)+位移量②JMPSHORT标号;IP←(IP)+8位位移量,短转移③JMPNEARPTR标号;IP←(IP)+16位位移量,近转移功能:无条件地转移到指令指定的标号处,执行从该标号开始的指令。其中:JMP为指令操作码。标号为8位或16位偏移量。4.2.1段内无条件转移1.段内直接转移682.段内间接转移指令格式:①JMP寄存器②JMPWORDPTR存储单元功能:程序转移的有效地址放在寄存器或存储单元中,执行指令时,将寄存器或字存储单元中的有效地址写入IP,从而实现转移。2.段内间接转移指令格式:694.2.2段间无条件转移1.段间直接转移指令格式:
①JMP标号②JMPFARPTR标号功能:无条件地转移到另一个代码段的标号处,执行从该标号开始的指令。标号所在段的段地址作为新的CS,标号在该段内的偏移地址作为新的IP。4.2.2段间无条件转移1.段间直接转移702.段间间接转移指令格式:JMPDWORDPTR存储单元功能:指令执行时,从指定存储单元连续取出两个字,第一个字送给IP,第二个字送给CS,从而实现段间转移。JMP指令不影响状态标志位。2.段间间接转移指令格式:714.3条件转移指令条件转移指令根据上一条指令所设置的条件标志作判断依据,条件满足则程序转移,否则顺序执行。这类转移指令的转移均属于短转移,即转移目标地址距当前IP所表示的地址的距离为-128~+127字节。语句格式为:助记符标号条件转移指令共有18条,可分成以下三类:①简单条件转移指令。②无符号数条件转移指令。③有符号数条件转移指令。条件转移指令均不影响状态标志位。4.3条件转移指令条件转移指令根据上一条指令所设置的条件724.3.1简单条件转移指令简单条件转移指令共有10条指令。它们是根据5个标志位CF、ZF、SF、OF、PF的两种状态(1或0)而设置的。一般适用于测试某一次运算结果的状态,并根据不同的状态标志产生不同的分支进行处理。下面分别举例说明。4.3.1简单条件转移指令简单条件转移指令共有10条指令73例4-5:假设AX中为一带符号数,求AX中数的绝对值。分析:求一个数的绝对值时,首先要测试该数的正负。我们可以测试其最高位,也可以测试符号标志。因此以下两个程序段均可求出AX中数的绝对值。程序段1:TESTAX,8000HJZNEXT;测试AX最高位,为零该数为正,转到NEXTNEGAX;否则,AX为负,求补运算NEXT:…………程序段2:ANDAX,AX;影响标志位JNSNEXT;测试AX的符号位,为正则转到NEXTNEGAX;否则,AX为负,求补运算NEXT:…………例4-5:假设AX中为一带符号数,求AX中数的绝对值。分析:74例4-6:计算X+Y,X和Y单元分别存放着一个16位有符号数。若结果有溢出,则转移到OVERFLOW处理。分析:两个有符号数相加,影响OF的值。若OF置1,则产生溢出。程序段如下:MOVAX,XADDAX,YJOOVERFLOW……;没有溢出,结果正确OVERFLOW:……;溢出处理例4-6:计算X+Y,X和Y单元分别存放着一个16位有符号数75例4-7:统计寄存器BX中1的个数。分析:要统计寄存器BX中1的个数,可以通过移位指令将BX中的每一位依次移入CF中,若CF=1则CL的值加1。这样就可以统计出BX中1的个数。程序段如下:MOVCL,0;保存BX中1的个数,初值为0AGAIN:ANDBX,BXJZEXIT,(BX)=0时,结束循环转EXITSALBX,1;将BX中的最高位移入CF中JNCAGAIN;如果CF=0转AGAININCCL;否则,CL的值加1JMPAGAIN;转AGAIN处继续处理EXIT:……
例4-7:统计寄存器BX中1的个数。分析:要统计寄存器BX中764.3.2无符号数条件转移指令这类指令往往跟在比较指令之后,视比较对象为无符号数。根据比较结果的不同状态,设置了高于(A-Above)、高于或等于(AE-AboveorEqual)、低于(B-Below)、低于或等于(BE-BeloworEqual)四条指令。4.3.2无符号数条件转移指令这类指令往往跟在比较指令之77无符号数条件转移指令①JA/JNBE用于两个无符号数a、b的比较,若a>b则条件满足,实现转移。②JNA/JBE用于两个无符号数a、b的比较,若a≤b则条件满足,实现转移。③JB/JNAE用于两个无符号数a、b的比较,若a<b则条件满足,实现转移。④JNB/JAE用于两个无符号数a、b的比较,若a≥b则条件满足,实现转移。四条指令的共同点是根据两个无符号数比较的结果,判断CF、ZF的状态是否满足转移条件,当满足条件时转移,否则顺序执行。适用于地址比较、循环次数比较或双精度数的低位字的比较等。无符号数条件转移指令①JA/JNBE78例4-8:阅读下面程序段,若寄存器AL的值分别取20H、5、0FFH和2,分析程序段的执行情况。程序段如下:CMPAL,5JANEXTADDAL,5NEXT:……分析:本程序段使用了无符号数跳转指令JA,若(AL)>5则转NEXT,否则顺序执行。(1)(AL)=20H>5,满足条件,跳至NEXT处执行。(2)(AL)=5,不满足条件,顺序执行“ADDAL,5”。(3)(AL)=0FFH,由于JA是无符号数跳转指令,对无符号数来说(AL)=0FFH>5,满足转移条件,故跳转至NEXT处执行。(4)(AL)=2<5,不满足条件,故顺序执行后继指令。例4-8:阅读下面程序段,若寄存器AL的值分别取20H、5、79例4-9:分析以下程序段:MOVSI,0;SI←0JP:MOVWORDPTR[SI],0;[SI]←0ADDSI,2;SI←(SI)+2CMPSI,0F000H;判断(SI)是否小于等于0F000HJNAJP;若小于等于,则转JP执行……分析:该程序段的功能是将当前数据段中偏移地址为0~0F000H的全部字存储单元清0,其中SI为送数指针。注意:在比较判断(SI)是否小于等于0F000H时,由于地址是无符号数,所以必须选用无符号数条件转移指令JNA,才能完成预定功能。例4-9:分析以下程序段:MOVSI,804.3.3带符号数条件转移指令在程序设计中,有时需要把处理对象视为带符号数(补码表示)。当比较两个带符号数的大小时,要选用带符号数条件转移指令。带符号数条件转移指令是根据条件标志ZF、SF、OF的特定组合来决定是否转移,共设置了大于、大于或等于、小于、小于或等于四条指令。4.3.3带符号数条件转移指令在程序设计中,有时需要把处81带符号数条件转移指令①JG/JNLE用于两个有符号数a、b比较。若a>b,即符号标志SF与溢出标志OF具有相同状态(SF=OF)且零标志ZF=0时,条件满足,实现转移。②JNG/JLE用于两个有符号数a、b的比较。若a≤b,即当SF≠OF或ZF=1时,条件满足,实现转移。③JL/JNGE用于两个有符号数a、b的比较。若a<b,即当SF≠OF时,条件满足,实现转移。④JNL/JGE用于两个有符号数a、b的比较。若a≥b,即当SF=OF时,条件满足,实现转移。四条指令的共同点是根据两个带符号数比较运算的结果,组合SF、OF标志,并利用ZF标志确定转移与否。下面举例说明条件转移指令的使用方法。带符号数条件转移指令①JG/JNLE82例4-10:假设有两个双精度数a和b,分别存储在AX、BX和CX、DX中,分析下列程序段的功能。程序段如下:CMPAX,CXJGUPPERJLLOWERCMPBX,DXJAUPPERLOWER:……UPPER:……图4-4
比较两个数大小算法流程图(AX)>(CX)(AX)<(CX)(BX)>(DX)NNNYYY标号UPPER处标号LOWER处分析:本程序段的功能是比较两个双精度数a和b的大小,若a﹥b则转向UPPER执行,否则转向LOWER执行。程序段流程图如图4-4所示。例4-10:假设有两个双精度数a和b,分别存储在AX、BX和83例4-11:将例4-9程序段中的JNA指令改成JNG指令,分析程序段功能。程序段如下:MOVSI,0;SI←0JP:MOVWORDPTR[SI],0;[SI]←0ADDSI,2;SI←(SI)+2CMPSI,0F000H;判断(SI)是否小于等于0F000HJNGJP;若小于等于,则转JP执行……例4-11:将例4-9程序段中的JNA指令改成JNG指令,分84分析:该程序段在进行比较判断时,选用了带符号数条件转移指令JNG。在第一次执行比较指令“CMPSI,0F000H”时,(SI)=2,它与带符号数0F000H(即-1000H)比较,显然2>-1000H,不满足“JNG”的转移条件而顺序执行后继语句。这样就只能将0送入偏移地址为0的字单元中,无法实现将当前数据段中偏移地址为0~0F000H的全部字存储单元清0。以上例子说明在设计分支程序时一定要注意正确选择条件转移指令。分析:该程序段在进行比较判断时,选用了带符号数条件转移指令J854.4分支程序设计方法在实际应用中,计算机处理的问题不可能全是顺序地执行操作,而往往需要对出现的各种情况进行分析判断,以决定进行不同的处理。这种分不同情况进行不同处理的程序结构就是分支程序结构。分支程序结构有两种形式,如图4-5所示:图4-5
分支程序结构示意图图(a)二分支结构判定条件为真NY分支1分支2图(b)多分支结构判定条件条件1分支2分支1分支n……条件2条件n不论哪一种形式,它们的共同特点是:运行方向是向前的,在某一种确定条件下,只能执行多个分支中的一个分支。4.4分支程序设计方法在实际应用中,计算机处理的问题不可864.4.1二分支程序设计所谓二分支程序设计,就是根据判定条件为真或为假,从两条分支中选择一条分支去执行。二分支程序中的一种特殊情况就是只有一个分支程序段,另一个分支是顺序执行,有时也把这种结构称为单分支结构。4.4.1二分支程序设计所谓二分支程序设计,就是根据判定87例4-12:分析下列程序段的结构。CMPAX,0JGEDONE;如果(AX)≥0,则转DONENEGAX;否则进行求补运算DONE:MOVRESULT,AX;保存结果……图4-6
单分支程序结构示意图(AX)≥0为真YYAX←-(AX)RESULT←(AX)N本程序段用来计算AX中带符号数的绝对值,是一个典型的单分支结构。程序段流程图如图4-6所示:例4-12:分析下列程序段的结构。CM88要设计双分支程序结构,首先要产生条件,然后对产生的条件进行分析判断,根据判断结果决定执行哪一个分支,最后转入相应程序段的起始地址去执行分支程序。其中产生条件的指令通常由指令系统中影响状态标志位的指令来产生,如算术运算指令(如ADD、SUB、CMP)、逻辑运算指令(如AND、TEST)、移位指令(如SHR、SHL)等等。要想用好这些指令,就要搞清楚这些指令的功能及其对标志位的影响。特别是要熟练掌握状态标志位CF、ZF、PF、SF和OF的含义。下面我们通过例子来介绍二分支程序设计方法。要设计双分支程序结构,首先要产生条件,然后对产生的条件进行分89例4-13:从键盘输入0~9中任一自然数x,求其立方值。若输入的字符不是0~9中的某数字,则显示“INPUTERROR!”,表明输入错误。分析:求一个数的立方值可以用乘法运算实现,也可以构造一立方表,通过查表实现。此处用查表法,查表法执行速度比较快。输入数据为0至9中任一自然数,用一字节单元存放其值;输出数据是该数的立方值,用一字单元存放其值。若输入时不慎按下0~9之外的字符键,则显示错误提示信息。存储单元和寄存器分配如下:字节变量X中存放键入的自然数x。字变量Y中存放x的立方值。AX是用来存放立方值的工作单元。BX是用来进行查表的工作单元。例4-13:从键盘输入0~9中任一自然数x,求其立方值。90图4-8
求立方值程序流程图(AL)是0~9中某一数字符Y将字符ASCII码转换成数字真值Y←求立方值N开始结束AL←从键盘输入字符显示错误提示信息假定立方表的首地址为TAB,表中共10项,每项占一个字,用来存放x的立方值。从表的结构可知,x的立方值在表中的存放地址与x有如下对应关系:(TAB+2*x)=x的立方值对于每个键入的x,从字单元TAB+2*x中取出的数据便是其立方值。从键盘接受数字输入使用1号系统功能调用,此时送入AL中的是x的ASCII码,而不是x的真值。所以要首先将x的ASCII码转换成x的真值,然后用TAB+2*x计算x立方值的存放地址,按此地址查到x的立方值。程序流程图如图4-8所示:图4-8求立方值程序流程图(AL)是0~9中某一数字符Y将91源程序如下:STACKSEGMENTSTACKDB200DUP(0)STACKENDSDATASEGMENTINPUTDB‘PLEASEINPUTX(0..9):$’TABDW0,1,8,27,64,125,216,343,5
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论