1 / 53

21 世纪高等院校规划教材

21 世纪高等院校规划教材. 汇编语言程序设计. 相 伟 主编 徐小平 李珍香 副主编. 中国水利水电出版社. 第 4 章 分支程序设计. 本章主要讲解分支程序设计的基本思想和设计方法。通过本章学习,读者应掌握以下内容: 段内寻址与段间寻址 无条件转移指令 条件转移指令 二分支程序设计方法 多分支程序设计方法. 4.1 转移地址的寻址方式.

yvonne
Download Presentation

21 世纪高等院校规划教材

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 21世纪高等院校规划教材 汇编语言程序设计 相 伟 主编徐小平 李珍香 副主编 中国水利水电出版社

  2. 第4章 分支程序设计 • 本章主要讲解分支程序设计的基本思想和设计方法。通过本章学习,读者应掌握以下内容: • 段内寻址与段间寻址 • 无条件转移指令 • 条件转移指令 • 二分支程序设计方法 • 多分支程序设计方法

  3. 4.1 转移地址的寻址方式 • Intel 8086/8088CPU中,程序的执行顺序是由代码段寄存器CS和指令指针IP确定的。CS包含当前指令所在代码段的段地址,IP则是要执行的下一条指令的偏移地址。通常情况下,程序是顺序执行的,即CPU取出指令后,自动形成下一条指令的地址,依指令序列顺序执行。但有时需要改变程序的流程,这就要给出目标指令的段地址(CS)和偏移地址(IP)值,这就是与转移地址有关的寻址方式。 • 与转移地址有关的寻址方式有四种:段内直接寻址、段内间接寻址、段间直接寻址和段间间接寻址。

  4. 4.1.1 段内寻址 • 段内寻址分为段内直接寻址和段内间接寻址两种方式。其转移方式是在当前代码段64KB范围内转移,因此不需要更改段地址CS的值,只要改变偏移地址IP的值即可。

  5. 1.段内直接寻址 • 指令中直接给出转移地址的偏移量(8位或16位),转移目标与转移指令在同一段内。转移指令执行后,CS值保持不变。转移的有效地址为当前的IP值与指令中指定的偏移量之和。即 • 目标地址 = IP(当前值)+ 偏移量 • 其中偏移量为8位或16位有符号数。若偏移量为正数,向前转移(即高地址方向);若偏移量为负数,则向后转移(即低地址方向)。另外,对8位偏移量,其转移范围为-128 ~ +127,称为短转移;对16位偏移量,其转移范围为-32768 ~ +32767,称为近转移。 • 短转移指令为2字节指令,IP的当前值为转移指令所在的IP值加2。近转移指令为3字节指令,IP的当前值为转移指令所在的IP值加3。

  6. 例4-1:分析下列指令。 • JMP SHORT DSP1 ;短转移指令 • JMP NEAR PTR DSP2 ;近转移指令 • 假设两条指令存放地址均为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去执行。

  7. 2.段内间接寻址 • 与段内直接寻址方式相同,转移目标与转移指令在同一段内。转移指令执行后,CS值保持不变。与段内直接寻址方式不同的是,转移的有效地址值存放在16位的通用寄存器或连续两个存储单元中。若有效地址在存储单元中,一定要指出存储单元为字型。

  8. 例4-2:假设(DS)=2000H,(BX)=3000H,(23000H)=2536H,分析下列指令。例4-2:假设(DS)=2000H,(BX)=3000H,(23000H)=2536H,分析下列指令。 • JMP BX 指令执行后,将BX的内容直接赋给IP。所以,(IP)= 3000H 。 • JMP WORD PTR[BX] 指令执行后,先计算出存储单元地址23000H,再从该单元中取出内容送给IP。所以,(IP)= 2536H 。

  9. 4.1.2 段间寻址 • 段间寻址分为段间直接寻址和段间间接寻址两种方式。其转移方式是从当前代码段跳转到另一个代码段,因此需要修改CS段地址和IP偏移地址的值。

  10. 1.段间直接寻址 • 在指令中直接给出了转移目标的段地址和偏移地址。只要用指令中指定的偏移地址代替IP寄存器的内容,用指令中指定的段地址代替段寄存器CS的内容就可以完成从一个段到另一个段的转移操作。段间直接转移通常叫远转移(far jump),指令的操作数必须附加FAR PTR操作符。

  11. 例4-3:执行如下指令 • JMP FAR PTR DSP • 假设指令存放地址为1000H:0200H,DSP的有效地址为3620H,段地址为2000H。 • 则指令执行后, (IP)= 3620H,(CS)= 2000H。程序转移到2000H:3620H处继续执行。

  12. 2.段间间接寻址 • 与段间直接寻址方式相同,转移目标与转移指令不在同一段内,转移指令执行后,CS和IP都发生变化。不同的是转移目标的偏移地址和段地址存储在两个连续的字存储单元中。因此指令中需要用DWORD PTR操作符将存储单元指定为双字单元。指令执行时,根据存储单元的寻址方式计算出存储单元地址,从该存储单元取第一个字传送到IP,取第二个字传送到CS,这样就可以实现段间转移。

  13. 例4-4:执行如下指令 • JMP DWORD PTR 6[BX] • 假设:(CS)= 1000H,(IP)= 0600H,(DS)= 2000H,(BX)= 1000H,(21006H)= 3000H,(21008H)= 6000H。 • 则指令执行后, (CS)= 6000H,(IP)= 3000H。 • 程序转移到6000H:3000H处继续执行。

  14. 4.2 无条件转移指令 • 无条件转移指令JMP使CPU无条件地转移到指令中指明的目的地址处执行。它不能构成分支程序,但在分支程序中却往往需要用它将各分支的出口重新汇集到一起。特别是当条件转移指令的转移范围超过-128 ~ +127个字节时,往往要借助无条件转移指令实现预定的转移。 • 转移可分成两类:段内转移和段间转移。段内转移是指在同一代码段内进行转移,此时只需改变IP寄存器的内容,即用新的转移目标地址代替原有的IP值就可达到转移的目的。段间转移则是要转到另一个段去执行程序,此时不仅要修改IP寄存器的内容,还需要修改CS寄存器的内容才能达到目的。因此,此时的转移目标地址应该由新的段地址和偏移地址两部分组成。

  15. 4.2.1 段内无条件转移 1.段内直接转移 • 指令格式: • ① JMP 标号 ;IP←(IP)+位移量 • ② JMP SHORT 标号 ;IP←(IP)+8位位移量,短转移 • ③ JMP NEAR PTR 标号 ;IP←(IP)+16位位移量,近转移 • 功能:无条件地转移到指令指定的标号处,执行从该标号开始的指令。 • 其中:JMP为指令操作码。标号为8位或16位偏移量。

  16. 2.段内间接转移 • 指令格式: ① JMP 寄存器 ② JMP WORD PTR 存储单元 • 功能:程序转移的有效地址放在寄存器或存储单元中,执行指令时,将寄存器或字存储单元中的有效地址写入IP,从而实现转移。

  17. 4.2.2 段间无条件转移 1.段间直接转移 • 指令格式: ① JMP 标号 ② JMP FAR PTR 标号 • 功能:无条件地转移到另一个代码段的标号处,执行从该标号开始的指令。标号所在段的段地址作为新的CS,标号在该段内的偏移地址作为新的IP。

  18. 2.段间间接转移 • 指令格式: JMP DWORD PTR 存储单元 • 功能:指令执行时,从指定存储单元连续取出两个字,第一个字送给IP,第二个字送给CS,从而实现段间转移。 • JMP指令不影响状态标志位。

  19. 4.3 条件转移指令 • 条件转移指令根据上一条指令所设置的条件标志作判断依据,条件满足则程序转移,否则顺序执行。这类转移指令的转移均属于短转移,即转移目标地址距当前IP所表示的地址的距离为-128 ~ +127字节。 • 语句格式为: 助记符 标号 • 条件转移指令共有18条,可分成以下三类: • ① 简单条件转移指令。 • ② 无符号数条件转移指令。 • ③ 有符号数条件转移指令。 • 条件转移指令均不影响状态标志位。

  20. 4.3.1 简单条件转移指令 • 简单条件转移指令共有10条指令。它们是根据5个标志位CF、ZF、SF、OF、PF的两种状态(1或0)而设置的。一般适用于测试某一次运算结果的状态,并根据不同的状态标志产生不同的分支进行处理。 • 下面分别举例说明。

  21. 例4-5:假设AX中为一带符号数,求AX中数的绝对值。例4-5:假设AX中为一带符号数,求AX中数的绝对值。 • 分析:求一个数的绝对值时,首先要测试该数的正负。我们可以测试其最高位,也可以测试符号标志。因此以下两个程序段均可求出AX中数的绝对值。 • 程序段1: TEST AX,8000H JZ NEXT ;测试AX最高位,为零该数为正,转到NEXT NEG AX ;否则,AX为负,求补运算 NEXT: …… …… • 程序段2: AND AX,AX ;影响标志位 JNS NEXT ;测试AX的符号位,为正则转到NEXT NEG AX ;否则,AX为负,求补运算 NEXT: …… ……

  22. 例4-6:计算X+Y,X和Y单元分别存放着一个16位有符号数。若结果有溢出,则转移到OVERFLOW处理。例4-6:计算X+Y,X和Y单元分别存放着一个16位有符号数。若结果有溢出,则转移到OVERFLOW处理。 • 分析:两个有符号数相加,影响OF的值。若OF置1,则产生溢出。 • 程序段如下: MOV AX , X ADD AX ,Y JO OVERFLOW ……;没有溢出,结果正确 • OVERFLOW:……;溢出处理

  23. 例4-7:统计寄存器BX中1的个数。 • 分析:要统计寄存器BX中1的个数,可以通过移位指令将BX中的每一位依次移入CF中,若CF=1则CL的值加1。这样就可以统计出BX中1的个数。 • 程序段如下: MOV CL ,0 ;保存BX中1的个数,初值为0 AGAIN:AND BX ,BX JZ EXIT ,(BX)= 0时,结束循环转EXIT SAL BX ,1 ;将BX中的最高位移入CF中 JNC AGAIN ;如果CF= 0转AGAIN INC CL ;否则,CL的值加1 JMP AGAIN ;转AGAIN处继续处理 EXIT : ……

  24. 4.3.2 无符号数条件转移指令 • 这类指令往往跟在比较指令之后,视比较对象为无符号数。根据比较结果的不同状态,设置了高于(A-Above)、高于或等于(AE-Above or Equal)、低于(B-Below)、低于或等于(BE-Below or Equal)四条指令。

  25. 无符号数条件转移指令 • ① 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的状态是否满足转移条件,当满足条件时转移,否则顺序执行。适用于地址比较、循环次数比较或双精度数的低位字的比较等。

  26. 例4-8:阅读下面程序段,若寄存器AL的值分别取20H、5、0FFH和2,分析程序段的执行情况。例4-8:阅读下面程序段,若寄存器AL的值分别取20H、5、0FFH和2,分析程序段的执行情况。 • 程序段如下: CMP AL , 5 JA NEXT ADD AL , 5 NEXT:…… • 分析:本程序段使用了无符号数跳转指令JA,若(AL)>5则转NEXT,否则顺序执行。 • (1)(AL)= 20H>5,满足条件,跳至NEXT处执行。 • (2)(AL)= 5,不满足条件,顺序执行“ADD AL, 5 ”。 • (3)(AL)= 0FFH,由于JA是无符号数跳转指令,对无符号数来说(AL)= 0FFH>5,满足转移条件,故跳转至NEXT处执行。 • (4)(AL)= 2<5,不满足条件,故顺序执行后继指令。

  27. 例4-9:分析以下程序段: • MOV SI , 0 ;SI←0 • JP :MOV WORD PTR [SI],0 ;[SI] ←0 • ADD SI , 2 ;SI←(SI)+2 • CMP SI ,0F000H ;判断(SI)是否小于等 于0F000H • JNA JP ;若小于等于,则转JP执行 • …… • 分析:该程序段的功能是将当前数据段中偏移地址为0 ~ 0F000H的全部字存储单元清0,其中SI为送数指针。 • 注意:在比较判断(SI)是否小于等于0F000H时,由于地址是无符号数,所以必须选用无符号数条件转移指令JNA,才能完成预定功能。

  28. 4.3.3 带符号数条件转移指令 • 在程序设计中,有时需要把处理对象视为带符号数(补码表示)。当比较两个带符号数的大小时,要选用带符号数条件转移指令。带符号数条件转移指令是根据条件标志ZF、SF、OF的特定组合来决定是否转移,共设置了大于、大于或等于、小于、小于或等于四条指令。

  29. 带符号数条件转移指令 • ① 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标志确定转移与否。 • 下面举例说明条件转移指令的使用方法。

  30. Y N (AX)>(CX) N Y (AX)<(CX) Y N (BX)>(DX) 标号UPPER处 标号LOWER处 图4-4比较两个数大小算法流程图 例4-10:假设有两个双精度数a和b,分别存储在AX、BX和CX、DX中,分析下列程序段的功能。 • 程序段如下: CMP AX ,CX JG UPPER JL LOWER CMP BX ,DX JA UPPER LOWER :…… UPPER :…… • 分析:本程序段的功能是比较两个双精度数a和b的大小,若a﹥b则转向UPPER执行,否则转向LOWER执行。程序段流程图如图4-4所示。

  31. 例4-11:将例4-9程序段中的JNA指令改成JNG指令,分析程序段功能。例4-11:将例4-9程序段中的JNA指令改成JNG指令,分析程序段功能。 • 程序段如下: MOV SI , 0 ;SI←0 JP:MOV WORD PTR [SI] , 0 ;[SI] ←0 ADD SI , 2 ;SI←(SI)+2 CMP SI , 0F000H ;判断(SI)是否小于等于0F000H JNG JP ;若小于等于,则转JP执行 ……

  32. 分析: • 该程序段在进行比较判断时,选用了带符号数条件转移指令JNG。在第一次执行比较指令“CMP SI , 0F000H ”时,(SI)= 2,它与带符号数0F000H(即-1000H)比较,显然2>-1000H,不满足“JNG”的转移条件而顺序执行后继语句。这样就只能将0送入偏移地址为0的字单元中,无法实现将当前数据段中偏移地址为0 ~ 0F000H的全部字存储单元清0。 • 以上例子说明在设计分支程序时一定要注意正确选择条件转移指令。

  33. 判定条件 Y N 判定条件为真 条件n 条件2 条件1 分支1 分支2 …… 分支n 分支1 分支2 图(a)二分支结构 图(b)多分支结构 图4-5分支程序结构示意图 4.4 分支程序设计方法 • 在实际应用中,计算机处理的问题不可能全是顺序地执行操作,而往往需要对出现的各种情况进行分析判断,以决定进行不同的处理。这种分不同情况进行不同处理的程序结构就是分支程序结构。 • 分支程序结构有两种形式,如图4-5所示: • 不论哪一种形式,它们的共同特点是:运行方向是向前的,在某一 种确定条件下,只能执行多个分支中的一个分支。

  34. 4.4.1 二分支程序设计 • 所谓二分支程序设计,就是根据判定条件为真或为假,从两条分支中选择一条分支去执行。二分支程序中的一种特殊情况就是只有一个分支程序段,另一个分支是顺序执行,有时也把这种结构称为单分支结构。

  35. Y (AX)≥0为真 N AX←-(AX) RESULT←(AX) Y 图4-6单分支程序结构示意图 例4-12:分析下列程序段的结构。 • CMP AX , 0 • JGE DONE ;如果(AX)≥0,则转DONE • NEG AX ;否则进行求补运算 • DONE:MOV RESULT,AX ;保存结果 • …… • 本程序段用来计算AX中带符号数的绝对值,是一个典型的单分支结构。程序段流程图如图4-6所示:

  36. 要设计双分支程序结构,首先要产生条件,然后对产生的条件进行分析判断,根据判断结果决定执行哪一个分支,最后转入相应程序段的起始地址去执行分支程序。其中产生条件的指令通常由指令系统中影响状态标志位的指令来产生,如算术运算指令(如ADD、SUB、CMP)、逻辑运算指令(如AND、TEST)、移位指令(如SHR、SHL)等等。要想用好这些指令,就要搞清楚这些指令的功能及其对标志位的影响。特别是要熟练掌握状态标志位CF、ZF、PF、SF和OF的含义。要设计双分支程序结构,首先要产生条件,然后对产生的条件进行分析判断,根据判断结果决定执行哪一个分支,最后转入相应程序段的起始地址去执行分支程序。其中产生条件的指令通常由指令系统中影响状态标志位的指令来产生,如算术运算指令(如ADD、SUB、CMP)、逻辑运算指令(如AND、TEST)、移位指令(如SHR、SHL)等等。要想用好这些指令,就要搞清楚这些指令的功能及其对标志位的影响。特别是要熟练掌握状态标志位CF、ZF、PF、SF和OF的含义。 • 下面我们通过例子来介绍二分支程序设计方法。

  37. 例4-13:从键盘输入0 ~ 9中任一自然数x,求其立方值。若输入的字符不是0 ~ 9中的某数字,则显示“INPUT ERROR!”,表明输入错误。 • 分析:求一个数的立方值可以用乘法运算实现,也可以构造一立方表,通过查表实现。此处用查表法,查表法执行速度比较快。 • 输入数据为0至9中任一自然数,用一字节单元存放其值;输出数据是该数的立方值,用一字单元存放其值。若输入时不慎按下0 ~ 9之外的字符键,则显示错误提示信息。 • 存储单元和寄存器分配如下: • 字节变量X中存放键入的自然数x。 • 字变量Y中存放x的立方值。 • AX是用来存放立方值的工作单元。 • BX是用来进行查表的工作单元。

  38. 开始 AL←从键盘输入字符 (AL)是0~9中某一数字符 N 显示错误提示信息 Y 将字符ASCII码转换成数字真值 Y←求立方值 结束 图4-8求立方值程序流程图 • 假定立方表的首地址为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所示:

  39. 源程序如下: • STACK SEGMENT STACK • DB 200 DUP(0) • STACK ENDS • DATA SEGMENT • INPUT DB ‘PLEASE INPUT X(0..9):$’ • TAB DW 0,1,8,27,64,125,216,343,512,729 • X DB ? • Y DW ? • INERR DB 0DH,0AH,’INPUT ERROR !$’ • DATA ENDS • CODE SEGMENT • ASSUME CS:CODE,DS:DATA,SS:STACK • BEGIN: MOV AX , DATA • MOV DS , AX • LEA DX , INPUT • MOV AH , 9 • INT 21H ;9号调用显示提示信息 • MOV AH , 1 • INT 21H ;AL←1号调用从键盘接受一字符输入

  40. CMP AL , ‘0’;若输入字符不是0~9中的某一数字,转LERR • JB LERR • CMP AL , ‘9’ • JA LERR • AND AL , 0FH • MOV X , AL ;X←x的真值 • ADD AL ,AL • MOV BL ,AL ;BX←2﹡x • MOV BH ,0 • MOV AX ,TAB[BX] • MOV Y , AX ;Y←x的立方值 • EXIT: MOV AH ,4CH • INT 21H ;结束程序,返回DOS状态 • LERR: MOV DX ,OFFSET INERR • MOV AH ,9 ;显示错误提示信息 • INT 21H • JMP EXIT • CODE ENDS • END BEGIN • 程序运行时,屏幕首先显示“PLEASE INPUT X (0..9):”,若键入 2,则2*x = 4,4→BX,从字单元TAB+4中取出2的立方值8送入Y中。若键入字符‘a’,因其不是‘0’~‘9’中的某一数字符,故显示“INPUT ERROR !”。

  41. 开始 Y A=0 N Y B=0 N Y C=0 N 显示”ERROR!” D←求三数和 结束 图4-9求三个数和的程序流程图 例4-14:将a、b、c三个十六位无符号数分别与零比较,如果三个数均不为零,求出三个数之和存放在变量d中(假设总和小于65535),若其中至少有一个数为零,则显示“ERROR!”。 • 分析:本题目的程序结构属于双分支结构的嵌套形式,对标志位的判断需要进行两次以上,才能确定其分支。 • 程序流程图如图4-9所示。 • 存储单元和寄存器分配如下: • 字变量A、B、C用来存放三个十六位无符号数; • 变量D用来存放三个数的和; • AX是用来求和的工作单元。

  42. 源程序如下: • STACK SEGMENT STACK • DB 200 DUP(0) • STACK ENDS • DATA SEGMENT • A DW 1234H • B DW 5678H • C DW 3562H • D DW ? • INERR DB 0DH,0AH,’ERROR !$’ • DATA ENDS • CODE SEGMENT • ASSUME CS:CODE,DS:DATA,SS:STACK • BEGIN: MOV AX , DATA • MOV DS , AX • MOV AX , 0 ;AX清0 • CMP A , 0 • JZ NEXT ;a=0,转NEXT • CMP B , 0 • JZ NEXT ;b=0,转NEXT

  43. CMP C , 0 • JZ NEXT ;c=0,转NEXT • ADD AX , A • ADD AX , B • ADD AX , C • MOV D , AX ;三数求和,结果存入D中 • JMP EXIT • NEXT: MOV DX , OFFSET INERR • MOV AH , 9 • INT 21H • EXIT: MOV AH , 4CH • INT 21H ;结束程序,返回DOS状态 • CODE ENDS • END BEGIN • 本程序运行时,由于A、B、C三个数均不为零,故求出三个数之和9E0EH存放在变量D中。读者可任意修改A、B、C三个变量的值,比较其运行结果。

  44. 例4-16:假设有三个单字节无符号数依次存放在BUF1开始的存储区中,试编写程序将它们从大到小排列并依次存放在BUF2开始的存储区中。例4-16:假设有三个单字节无符号数依次存放在BUF1开始的存储区中,试编写程序将它们从大到小排列并依次存放在BUF2开始的存储区中。 分析(方法一)∶将三个无符号数依次送入AL、BL、CL三个工作单元中,然后在三个工作单元之间比较大小,排好顺序后依次存放在BUF2开始的存储区中。 • 程序流程图如图4-11所示: • 存储单元和寄存器分配如下: • BUF1用来保存原始数据的存储区首址; • BUF2用来存放已排序数据的存储区首址; • AL、BL、CL用来存放原始数据的工作单元; • SI用来指向BUF1的工作指针 • DI用来指向BUF2的工作指针。

  45. 开始 将三个数分别送到AL、BL、CL中 Y N (AL)≥(BL) N Y Y N (BL)≥(CL) (BL)≥(CL) (AL)≥(CL) (AL)≥(CL) Y Y CL、BL、AL AL、BL、CL N N BL、AL、CL BL、CL、AL CL、AL、BL AL、CL、BL 结束 图4-11将三个数由大到小排列程序流程图 源程序如下: STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS DATA SEGMENT BUF1 DB 56H,12H,78H BUF2 DB 3 DUP(0) DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK BEGIN:MOV AX , DATA MOV DS , AX MOV SI , OFFSET BUF1 ;SI指向BUF1存储区 MOV DI , OFFSET BUF2 ;DI指向BUF2存储区 MOV AL , [SI] MOV BL , [SI+1] ;将原始数据分别送入AL、BL、CL MOV CL , [SI+2] CMP AL , BL JAE NEXT1 CMP BL , CL

  46. JAE NEXT3 • MOV [DI] , CL • MOV [DI+1] , BL • MOV [DI+2] , AL • JMP EXIT • NEXT1:CMP BL , CL • JAE NEXT2 • CMP AL , CL • JAE NEXT21 • MOV [DI] , CL • MOV [DI+1] , AL • MOV [DI+2] , BL • JMP EXIT NEXT2:MOV [DI] , AL • MOV [DI+1] , BL • MOV [DI+2] , CL • JMP EXIT • NEXT21:MOV [DI] , AL • MOV [DI+1] , CL • MOV [DI+2] , BL • JMP EXIT • NEXT3:CMP AL , CL • JAE NEXT31 • MOV [DI] , BL • MOV [DI+1] , CL • MOV [DI+2] , AL • JMP EXIT • NEXT31:MOV [DI] , BL • MOV [DI+1] , AL • MOV [DI+2] , CL • EXIT:MOV AH , 4CH • INT 21H • CODE ENDS • END BEGIN • 程序运行后,BUF2存储区中依次存储 78H 56H 12H 。

  47. 由图4-11可以看到,用此种方法来比较三个数的大小是非常麻烦的,编程工作量很大。下面我们再来介绍一种简单方法。由图4-11可以看到,用此种方法来比较三个数的大小是非常麻烦的,编程工作量很大。下面我们再来介绍一种简单方法。

  48. 开始 将三个数分别送到AL、BL、CL中 Y (AL)≥(BL) N (AL)和(BL)交换 Y (AL)≥(CL) N (AL)和(CL)交换 Y (BL)≥(CL) N (BL)和(CL)交换 按AL、BL、 CL顺序依次存回 结束 图4-12将三个数由大到小排列程序流程图 (方法二): • 首先将三个无符号数依次送入AL、BL、CL三个工作单元中,然后比较AL和BL,若AL小于BL,则将两者内容交换;再比较AL和CL,若AL小于CL,将两者内容交换,这样AL中保存的就是三个数中的最大者。再比较BL与CL,若BL小于CL,就将两者内容交换,即将最小的数放在CL中。最终将三个数按由大到小的顺序依次存放在AL、BL和CL中。 • 程序流程图如图4-12所示: • 存储单元和寄存器分配同方法一。 • 源程序如下:

  49. STACK SEGMENT STACK • DB 200 DUP(0) • STACK ENDS • DATA SEGMENT • BUF1 DB 56H,12H,78H • BUF2 DB 3 DUP(0) • DATA ENDS • CODE SEGMENT • ASSUME CS:CODE,DS:DATA,SS:STACK • BEGIN:MOV AX , DATA • MOV DS , AX • MOV SI , OFFSET BUF1 • MOV DI , OFFSET BUF2 • MOV AL , [SI] • MOV BL , [SI+1] • MOV CL , [SI+2] • CMP AL , BL • JAE NEXT1 • XCHG AL , BL • NEXT1:CMP AL , CL • JAE NEXT2 • XCHG AL , CL • NEXT2:CMP BL , CL • JAE NEXT3 • XCHG BL , CL • NEXT3:MOV [DI] , AL • MOV [DI+1] , BL • MOV [DI+2] , CL • MOV AH , 4CH • INT 21H • CODE ENDS • END BEGIN • 读者可对照流程图自己分析源程序。显然第二种方法比较次数更少,编程工作量也大大减少。

  50. 4.4.2 多分支程序设计 • 在实际应用中,有时会碰到多分支程序结构。多分支程序结构相当于一个多路开关,有多个并行的分支程序段,每个分支程序段与一个条件相对应,执行时只能执行其中一个分支段。若用条件转移语句实现,则N条分支需要N-1个条件转移指令完成,转移速度慢,程序代码长。因此常采用地址表法来实现。 • 地址表法的设计思想是:在程序段中开辟一些存储空间,形成一张地址表,用于依次存放各分支程序段的程序入口地址。程序执行时,首先判断出满足某分支程序段的条件,由此求出该分支程序段的编号。该编号乘2(段内转移),或乘4(段间转移)得到相对地址表的偏移量,再加上地址表首地址,即得到地址表中的一个地址。在这个地址表地址中存放着分支程序段的偏移地址(或偏移地址+段地址),转到该地址去执行程序,即执行该分支程序段。

More Related