第七章 分支与转移程序_第1页
第七章 分支与转移程序_第2页
第七章 分支与转移程序_第3页
第七章 分支与转移程序_第4页
第七章 分支与转移程序_第5页
已阅读5页,还剩81页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第七章顺序 分支 循环程序设计通过这一章的学习 主要掌握各种转移指令或者循环指令的使用方法 能够在程序中使用各种程序结构 掌握汇编语言程序设计的完整步骤 要求能够上机调试程序 目的和要求 主要掌握各种转移指令或者循环指令的使用方法 能够在程序中使用各种程序结构 掌握汇编语言程序设计的完整步骤 要求能够上机调试程序 7 1 1汇编语言程序的设计步骤 选择算法 决定解决问题的总体思路 最后确定为计算机可以执行各种算法 绘制流程图 对于编写较大的程序 这一个步骤是很有效的 把算法思想具体化为图形表示 这使以后编制的程序结构更加清晰 更不容易出现逻辑错误 3 编制程序 根据流程图写程序 确定程序中的段结构 以及具体使用的指令和伪指令 源程序文件必须以 ASM 作为后缀名 否则汇编程序会拒绝汇编该源程序 4 汇编过程 使用汇编程序MASM EXE对源程序进行汇编 生成目标代码 如果检查出语法错误 那么返回到第三步修改源程序 直到没有语法错误为止 连接过程 需要使用连接程序LINK EXE把汇编程序汇编得到的目标代码文件 OBJ 为后缀 转变为可执行文件 EXE 为后缀 如果有多个OBJ文件 就需要把它们连接在一起成为一个EXE文件 6 调试过程 得到可执行文件以后就要进行程序调试 这是开发周期中花费时间最长的一个过程 使用DEBUG EXE调试程序 观察程序的执行结果是否正确 如果发现逻辑错误 就回到第三步重复上面的编制 汇编 连接过程 7 1 2程序的基本结构汇编语言程序和高级语言程序的基本程序结构一样 分为三种 顺序结构 分支结构和循环结构 通过三种基本结构的组合和嵌套 又可以形成更复杂的程序结构 基本程序结构又可以有一些变种 在汇编语言中主要使用5种结构 其中 1 2 4 是基本结构 3 5 是变种 注意流程图中的符号 学会画流程图 7 2顺序结构程序设计顺序结构是最简单的程序流程 指令按照在内存中的地址顺序依次被执行 没有任何的流程改变现象 例7 2 1计算Z 3X Y 5 2 1 数据分析 表达式中有三个变量X Y Z 可以使用三个内存单元来表示 题目没有指明变量的变化范围 使用字节 字为单位都可以 教材中是以字为单位 2 算法分析 3X 2X X一条移位指令和一条加法指令可以实现3X Y 5 一条加法指令和一条减法指令可以实现 3X Y 5 2 除以2可以使用右移指令实现总体上程序应该为顺序结构 按照表达式规定的顺序使用加法 减法 移位指令相结合可以实现要求的全部运算 3 绘制流程图并写出相关程序主体 开始 计算2X X 计算3X Y 5 计算 3X Y 5 2 结束 MOVAX VARXSHLAX 1ADDAX VARX ADDAX VARYSUBAX 5 SARAX 1MOVVARZ AX 4 选择一种程序框架 把程序主体添加到框架中就可以完成整个源程序的编制过程 5 汇编过程 使用MASM EXE汇编工具对源程序文件 ASM文件 进行汇编 检查有没有语法错误 如果有就进入编辑器进行修改 最后 生成目标代码文件 OBJ文件 6 连接过程 使用LINK EXE连接工具把OBJ文件组织为真正的可执行文件 EXE文件 7 使用DEBUG调试可执行程序 观察程序中有没有逻辑错误 如果有就进入编辑器进行修改 直到程序运行结果无误为止 7 3分支程序设计分支结构在程序流程中是最常用的一种 任何实用的程序都需要对计算结果或某些必要的测试条件进行判断 根据判断的逻辑结果来决定是否改变程序执行的流程 汇编语言中 实现分支结构的指令是转移类指令 这类指令可以通过修改CS和IP的内容来改变程序执行的流程 其实 程序中的很多循环结构也是通过转移指令来实现的 因为循环结构就是分支结构的一种特例 7 3 1转移指令转移指令分为无条件和条件两种 无条件转移指令一定会改变程序执行的流程 改变下一条将要执行的指令地址 条件转移指令则会对特定的标志位进行判断 如果标志位的状态满足条件 那么它会改变程序执行的流程 如果不满足条件 那么不会改变程序的流程 两种转移指令的功能都不可忽视 在程序中都是经常使用的 一 无条件转移指令指令格式 JMP目标地址功能 无条件的修改IP或者CS IP中的内容 改变下一条将要执行的指令地址 即跳转到目标地址继续执行程序 标志位影响 无 JMPL1MOVAX 0 L1 MOVAX 0FFFFH 按照正常的执行流程 执行完JMPL1指令以后 应该执行MOVAX 0指令 但是由于程序执行流程已经改变到L1标号指明的地址 所以下一条将要执行的指令变成了MOVAX 0FFFFH指令 JMP指令的转移类型分为两种 段内转移和段间转移 1 段内转移JMP指令本身和目标地址在同一个代码段内 这种转移只需要修改IP的内容 而不需要改变CS的内容 1 段内直接转移格式 JMP标号机器指令的格式由两部分构成 OPCODE和DISP OPCODE是操作码 DISP是一个8位或16位的补码DISP表示的含义是标号地址相对于JMP指令的字节距离 DISP 标号偏移量 JMP指令偏移量上面这个表达式的计算是汇编程序在汇编过程中完成的 如果没有汇编语言 直接使用机器指令编程 那么DISP的计算就必须由程序员来完成 标号地址 JMP指令地址 DISP 0标号地址 JMP指令地址 DISP 0功能 IP IP DISP IP DISP注意这个加法 这是两个补码的加法 DISP可以是正数 也可以是负数 但是 IP 总是理解为正数 把第16位 超出字的范围 理解为符号位 IP 的第16位总是理解为0 DISP的第16位由它自己的符号位决定 举例 IP 1100101001101011DISP 11100110 IP DISP 01100101001101011 1111111111110011001100101001010001注意 相加的结果总是一个正数 补码加法完毕以后应当重新把 IP 看作无符号数 段内直接转移在机器指令中又可以分为短跳转和长跳转两种情况 指令中的DISP字段是由汇编程序在汇编过程中计算并生成的 如果汇编程序计算出的DISP在 128 127范围内 那么生成的DISP只有一个字节 这种情况称为短跳转 如果DISP超过了 128 127这个范围 那么生成的DISP字段将在指令中占用一个字 这种情况称为长跳转 转移范围为 32768 32767 段的最大空间就是65536字节 长跳转已经可以在整个代码段中任意的实现转移 2 段内间接转移JMP指令针对的目标偏移量存放在16位的通用寄存器或字内存单元中 指令格式 JMP通用寄存器名称JMP字内存单元功能 IP 通用寄存器 IP EA 例子 JMPBX功能 IP BX JMPWORDPTR SI 功能 IP DS SI 注意直接段内转移和间接段内转移的区别 直接段内转移 由机器指令的DISP字段给出目标地址相对于JMP指令的带符号字节距离 完成的功能是 IP IP DISP 间接段内转移 由16位通用寄存器或字内存单元直接给出IP寄存器新的内容 段内间接寻址方式 JMPWORDPTRVARJMPWORDPTR BX 举例 如果BX 100H 100H 4100H分析执行下面指令后 指令地址分别 JMPBXJMP BX 2 段间转移标号地址和JMP指令本身不在同一个代码段内 这类转移必须同时修改CS和IP的内容 才能完成正确的转移操作 1 段间直接转移指令格式 JMPFAR类型的标号JMPFARPTR标号第二种格式是强制指定标号的临时类型属性为FAR 无论该标号定义时是什么类型 在这里一定作为FAR类型来引用 机器指令中除了OPCODE字段外 还有两个16位的字段 分别表示目标地址的偏移量和段基值 功能 IP 目标地址偏移量CS 目标地址段基值同时修改CS IP中的内容 实现段间转移 下图给出的是段间直接转移指令机器码示意图 执行时把偏移量送给IP 段基址送给CS 即可实现段间直接转移 2 段间间接转移这种转移方式所使用的目标地址只能是存放在双字内存单元中的内容 指令格式 JMPDWORDPTR双字单元起始偏移量功能 IP EA CS EA 2 例子 ADR1DDL1 JMPDWORDPTRADR1功能 实现段间转移 目标地址为L1标号所在的位置 它对应的逻辑地址存放在ADR1双字单元中 例子 JMPDWORDPTR BX DI 双字单元有效地址 EA BX DI 采用基址变址寻址方式 功能 IP EA CS EA 2 二 条件转移指令统一的汇编格式 JXX目标地址功能 根据前一条指令所影响或设置的某些标志位状态作为判断条件 当条件满足时 把程序流程转移到指定的目标地址 当条件不满足时 不改变程序流程 CPU会顺序执行下一条指令 标志位影响 无 只使用标志位作为判断条件 不会去修改它 条件转移指令的机器指令格式 总是占用2个字节 前一个字节是OPCODE 后一个字节是带符号的相对位移量 DISP 由于在条件转移指令中 DISP仅8位 那么跳转范围一定是 128 127字节 只能是短跳转 这一点对于所有条件转移指令来说都是一样的 如果需要条件转移的转移范围得到扩大 那么必须结合使用无条件转移 因为只有无条件转移指令提供长跳转和段间转移 注意 在执行条件转移指令前 一般需要执行一条算术运算指令或逻辑运算指令对特定标志位产生有意义的影响 根据条件转移指令所判断的标志位可以把它们分为三类 单条件转移 无符号数条件转移 有符号数条件转移 条件转移指令是用于实现分支和循环结构的基础 但是程序的结构却是程序员可以自由选择的 左边的图为非结构化的分支结构 右边为结构化的 在非结构化的分支结构中 每一个分支的出口可能不一样 如果要分析这一个分支结构 那么必须在源程序中找到所有分支的出口 如果要调试它 那么需要在每一个出口都设置断点 或者单步跟踪每一个出口 非结构化的分支会造成程序的可读性下降 调试难度加大 如果采用结构化的分支 那么所有分支的出口都是一致的 程序的分析和调试都非常方便 只需要注意一个出口 在程序设计中应该养成结构化编程的习惯 1 单条件转移指令这一类条件转移指令只对某一个标志位的状态进行判断 并决定是否进行转移 1 单标志位转移单标志位转移指令总共有5对 能对5个标志位 CF ZF SF OF PF各自的状态进行判断 例7 3 1编写一段程序判断两个字节变量DB1和DB2的内容是否相同 如果相同则把AL清0 否则置全1 教材上的程序片段 MOVAL DB1CMPAL DB2JZL1MOVAL 0FFHJMPL2 无条件转移对于实现分支结构也是必不可少的L1 MOVAL 00HL2 MOVAH 4CHINT21H注意分析 上面的条件转移有什么样的缺陷 如果JZL1指令和L1标号之间的字节距离超过127 那么在汇编过程中就会出现语法错误 从上面的例子可以看出 条件转移指令不适合直接用于距离较远的转移 一般来说 应该结合无条件转移指令在分支结构中实现长距离转移 就上面的例子 我们通过它的流程图来得到合理的源程序 根据流程图写出相关程序主体 CMPAL DB2JZL1JMPL2 MOVAL DB1 Y L1 N L2 L3 L1 MOVAL 0JMPL3 L2 MOVAL 0FFH L3 MOVAH 4CHINT21H 按照这种规则设计的分支结构中 所有长距离的流程转移都是由无条件转移指令实现的 避免了直接使用条件转移指令作长跳转 在今后的程序设计中 需要逐渐养成这样的编程习惯 对汇编语言进一步熟悉之后 在编制一些小程序或者程序片段的时候 可以跳过流程图绘制这一步 直接进行程序的编制 2 另一种单条件转移指令格式 JCXZ目标地址功能 判断 CX 是否等于0 如果等于0 则跳转到目标地址 否则顺序执行下一条指令 这一条指令主要用于和循环指令配合使用 以实现程序中循环结构 因为循环指令就是使用CX寄存器作为计数器实现计数循环的 在讲到循环指令的时候 我们会详细说明这条指令的具体用途 注意 JCXZ是对 CX 进行判断 而不是使用ZF标志位 看下面的程序片段 MOVAX 34HMOVCX 34HCMPCX AXJCXZL1 L1 程序中 JCXZ指令并不会跳转到L1 因为 CX 不等于0 ZF标志的取值并不会影响它的判断 提问 1 转移指令的实质 2 转移指令目的操作数 3 直接转移和间接转移的区别 4 段内转移和段间转移的区别 5 转移指令的寻址方式有哪些 2 无符号数条件转移指令这是一组指令 用于对两个无符号数比较的结果进行判断 从而决定是否进行程序的流程转移 使用前提 使用这组指令之前 要保证上一条被执行的指令是CMP指令 并且程序员把两个参与比较的操作数看作无符号数 这组指令在逻辑上把CMP指令的目的操作数称为A数据 把源操作数称为B数据 通过CF标志和ZF标志的状态来判断A B两个数据的大小关系 决定是否跳转 JA A B成立则转移JNBE A B不成立则转移使用这两个助记符含义是相同的 对应同一条机器指令 判断规则 CF 0ANDZF 0 转移 否则不转移 CF 0 A B最高位不产生借位 够减 A BZF 0 A B结果不为0 A B综合分析所得 A B JAE A B成立则转移JNB A B不成立则转移两个助记符对应同一条机器指令 判断规则 CF 0ORZF 1 转移 否则不转移 CF 0 A B最高位不产生借位 够减 A BZF 1 A B结果为0 A B综合分析所得 A B 可以看出 单凭CF 0这一个条件已经可以实现对条件A B的判断 但是这条指令仍然在硬件逻辑上使用了ZF标志 用JNC指令可以达到和JAE JNB指令相同的功能 但是JNC指令不要求上一条所执行的指令一定是CMP指令 还可以是移位指令等 JNC不一定用于判断两个无符号数之间的大小关系 JB A B成立则转移JNAE A B不成立则转移两个助记符对应同一条机器指令 判断规则 CF 1ANDZF 0 转移 否则不转移 CF 1 A B最高位产生借位 不够减 A BZF 0 A B的结果不为0 A B综合分析所得 A B 其实单凭CF 1这一个条件就可以断定A B的结果 只是这条指令在硬件逻辑上同时也使用了ZF标志 使用JC指令可以达到同样的转移效果 和JNC指令一样 它不一定用于判断两个无符号数的大小关系 应用范围比JB JNAE指令更宽广 JBE A B成立则转移JNA A B不成立则转移两个助记符对应同一条机器指令 判断规则 CF 1ORZF 1 转移 否则不转移 CF 1 A B最高位产生借位 不够减 A BZF 1 A B的结果为0 A B综合分析所得 A B 例7 3 2数据段中的ARY数组中存放了10个字节型的无符号数 从数组中找出最大的数保存到MAX字节单元中 1 数据分析 数组ARY需要10个字节的空间 可以使用DUP关键字来定义 MAX字节单元用于存放最终结果 2 算法分析 把数组中的第0个数据首先存放到一个寄存器中 这里选用AL 然后把寄存器中的数据和数组中的每一个数据按顺序作比较 当比较过程中每遇到一个大于寄存器中数据的数组元素 就用当前的数组元素修改寄存器的内容 保持寄存器中的数据总是当前最大的 由于需要逐个访问数组中的元素 需要使用一个基址或变址寄存器作为一维数组的浮动下标 这里选用SI 还需要一个计数器 对访问次数进行记数 保证对数组的访问不会越界 这里数组中有10个元素 使用CX来完成记数的功能 3 绘制流程图并写出相关程序主体 开始 初始化SI CX AL 进入循环 修改SI使它指向下一个数据 MOVSI OFFSETARYMOVCX 9MOVAL SI LOP INCSI AL SI AL SI Y L1 N L2 L3 LOP L3 CMPAL SI JBL1JMPL3 L2 L3 L1 MOVAL SI JMPL3 可省略 结束 CX CX 1 L3 DECCX JNZLOP1 条件转移实现循环 CX 0 MAX AL MOVMAX AL MOVAH 4CHINT21H N LOP1 L3 3 带符号数条件转移指令一组指令 用于对两个带符号数比较的结果进行判断 从而决定是否进行程序的流程转移 使用前提 使用这组指令之前 要保证上一条被执行的指令是CMP指令 并且程序员把两个参与比较的操作数看作带符号数 这组指令在逻辑上把CMP指令的目的操作数称为A数据 把源操作数称为B数据 通过OF标志 SF标志和ZF标志的状态来判断A B两个数据的大小关系 决定是否跳转 JG A B成立则转移JNLE A B不成立则转移判断规则 SF OFANDZF 0 转移 否则不转移 SF OF 参见教案对CMP指令的分析 符号标志等于溢出标志 A B的正确结果应该是一个正数或者是0 A BZF 0 A B结果不为0 A B综合分析所得 A B JGE A B成立则转移JNL A B不成立则转移判断规则 SF OFORZF 1 转移 否则不转移 SF OF A BZF 1 A B结果为0 A B综合分析所得 A B其实 从逻辑角度上说 ZF 1这个条件可以去掉 但是指令实际使用的硬件判断逻辑就是这样设计的 JL A B成立则转移JNGE A B不成立则转移判断规则 SF OFANDZF 0 转移 否则不转移 SF OF 符号标志和溢出标志不相等 A B的正确结果应该是负数 A BZF 0 A B的结果不为0 A B综合分析所得 A B从逻辑上讲ZF 0这个条件可以不用 但是为了硬件上保证几条带符号转移指令的设计一致和方便 在硬件逻辑中确实使用了ZF 0这个条件 JLE A B成立则转移JNG A B不成立则转移判断规则 SF OFORZF 1 则转移 否则不转移 SF OF A BZF 1 A B综合结果 A B 例 例7 3 2改一下 把数组中存放的无符号数改成带符号数 不但找出数组中最大的数 而且要求找出最小的数 数据分析 ARY字节数组占用10个字节MIN字节单元用于存放最小值MAX字节单元用于存放最大值 算法分析 虽然增加了一个求最小值的过程 但是这个过程可以放在求最大值的循环中一起完成 只是在循环中增加一个比较和一个分支 在前面的例子中使用AL寄存器存放当前比较的最大值 这里增加AH寄存器存放当前比较的最小值 3 绘制流程图并写出相关程序主体 开始 初始化SI CX AL AH 进入循环 修改SI使它指向下一个数据 MOVSI OFFSETARYMOVCX 9MOVAL SI MOVAH SI LOP INCSI AL SI AL SI Y L1 N L2 L3 LOP L3 CMPAL SI JBL1JMPL3 L2 L3 L1 MOVAL SI JMPL3 可省略 L3 JGL4JMPL6 L5 L6 L4 MOVAH SI JMPL6 可省 AH SI L3 AH SI Y L4 N L5 L6 CX CX 1 L6 DECCX JNZLOP1 CX 0 N LOP1 上一个例子中的两个分支结构实际上在程序结构上还可以进一步优化 使程序的执行更有效率 AL SI AL SI 7 3 3分支程序设计汇编语言程序中的分支结构都是结合使用条件转移指令和无条件转移指令来构造的 分支结构分为两种 1 IF THEN ELSE结构 双分支结构 把程序流程分为两支 这种结构和条件转移指令本来的特征是一致的 2 CASE结构 多分支结构 从逻辑上讲 多分支结构可以通过嵌套使用双分支结构来实现 但是执行效率不高 可以通过建立多分支表的方法来建立效率较高的多分支结构 1 使用条件转移指令实现分支结构 包括双分支 多分支 例7 3 3 编写计算下面函数值的程序 1X 0Y 0X 0 1X 0设输入数据为X 输出数据Y 且皆为字节变量 程序流程图如图所示 程序如下 流程图 X 0 Y 1 X 0 Y 0 Y 1 CMPX 0JLL1JMPL2L1 MOVY 1JMPL5L2 JZL3JMPL4L3 MOVY 0JMPL5L4 MOVY 1L5 MOVAH 4CHINT21H N L1 Y L2 Y L3 N L4 L5 L5 STACKSEGMENTSTACKDW100DUP 0 STACKENDSDATASEGMENTXDB 10YDB DATAENDSCODESEGMENTASSUMEDS DATA SS STACK CS CODESTART MOVAX DATAMOVDS AXCMPX 0 与0进行比较JGEL1 X 0转L1 MOVY 1 X 0时 1 YJMPEXITL1 JGL2 X 0转A2MOVY 0 X 0时 0 YJMPEXITL2 MOVY 1 X 0 1 YEXIT MOVAH 4CHINT21HCODEENDSENDSTART 2 使用跳转表实现多分支结构多分支结构相当于高级语言中的CASE语句 可以通过嵌套使用双分支结构来实现 但是进入每一个分支的时间可能会有差异 分支越多 进入每一个分支的时间差异就越大 下面是嵌套使用双分支结构实现的多分支结构流程图 时间 T A 时间 T B 时间 T C D T 2T 3T 3T 典型的多分支结构要求程序进入每一个分支所花费的时间大致是相当的 典型的多分支结构流程图如下 时间 T A B C D T T T T 典型的多分支结构在汇编语言这个层面只能使用跳转表来实现 1 跳转表由各分支的入口地址构成段内跳转表 把各个分支在代码段内的起始偏移量 字 组织到一个数组中 使用无条件段内间接转移指令使用其中的某一个偏移量 转移到该偏移量对应的分支入口 段间跳转表 把各个分支的完整逻辑地址 双字 组织到一个数组中 使用无条件段间间接转移指令使用其中某一个逻辑地址 转移到该逻辑地址对应的分支入口 2 跳转表由无条件转移指令构成 7 4循环程序设计程序设计中的所有循环结构可以使用条件转移指令来实现 高级语言中的WHILE循环 DO

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论