《单片机原理与接口技术》第4章汇编语言程序设计.ppt
《《单片机原理与接口技术》第4章汇编语言程序设计.ppt》由会员分享,可在线阅读,更多相关《《单片机原理与接口技术》第4章汇编语言程序设计.ppt(36页珍藏版)》请在装配图网上搜索。
高等职业教育计算机类课程规划教材 单片机原理与接口技术 大连理工大学出版社 第4章汇编语言程序设计 4 1概述4 2汇编语言伪指令4 3简单程序设计4 4循环程序设计4 5子程序设计4 6查表及散转程序设计4 7实用程序举例 4 1 1程序设计语言简介1 机器语言当指令和地址采用二进制代码表示时 机器能够直接识别 因此称为机器语言 机器指令代码是0和1构成的二进制数信息 与机器的硬件操作一一对应 使用机器语言可以充分发挥计算机硬件的功能 但是 机器语言难写 难读 难交流 而且机器语言随计算机的型号不同而不同 因此移植困难 然而 无论人们使用什么语言编写程序 最终都必须翻译成机器语言 机器才能执行 4 1概述 2 汇编语言汇编语言是采用易于人们记忆的助记符表示的程序设计语言 方便人们书写 阅读和检查 一般情况下 汇编语言与机器语言一一对应 用汇编语言编写的程序称为汇编语言源程序 源程序 把汇编语言源程序翻译成机器语言程序的过程称为汇编 完成汇编过程的程序称为汇编程序 汇编产生的结果是机器语言程序 目标程序 汇编语言源程序从目标代码的长度和程序运行时间上看与机器语言程序是等效的 不同系列的机器有不同的汇编语言 因此汇编语言源程序在不同的机器之间不能通用 3 高级语言高级语言是对计算机操作步骤进行描述的一整套标记符号 表达格式 结构及其使用的语法规则 它是一种面向过程的语言 使用一些接近人们书写习惯的英语和数学表达式的语言去编写程序 使用方便 通用性强 不依赖于具体计算机 目前 世界上的高级语言有数百种 用高级语言编写的源程序 同样需要翻译成用各种机器语言表示的目标程序 计算机才能解释执行 完成翻译过程的程序称为编译程序或解释程序 高级语言程序所对应的目标代码往往比机器语言要长的多 运行时间也更多 4 1 2汇编语言源程序的设计步骤汇编1 分析任务当我们要编写某个功能的应用程序时 首先应该详细分析给定的任务 明确哪些是任务所提供的基本条件 哪些是任务要解决的具体问题 哪些是任务所期望的最终目标 2 确定算法 任务明确之后 下一步就是确定解决问题的方法 将给定的任务转换成计算机处理模式 即通常所说的算法 对于较复杂的任务 需要先用数学方法把问题抽象出来 往往同一个数学表达式可以用多种算法实现 我们应综合考虑寻找出其中的最佳方案 使程序所占内存小 运行时间短 3 画程序流程图画流程图是把所采用的算法转换为汇编语言程序的准备阶段 选择合适的程序结构 把整个任务细化成若干个小的功能 使每个小功能只对应几条语句 4 分配资源在用汇编语言进行程序设计时 我们直接面向的是计算机的最底层资源 在编写代码之前需要对内存区域进行分配 并确定程序和数据的存放地址 5 编写代码在画好流程图并分配了相关资源后 就可以编写程序代码了 6 程序修改与调试当一个汇编语言程序编好后难免有错误或需要进一步优化的地方 必须进行调试 修改 在源程序的汇编过程中用户很容易发现程序中存在的语法错误 但查找和修改程序中的逻辑错误就不那么简单 我们需要借助开发系统所提供的程序单步操作或设置断点等调试手段予以排除 4 2汇编语言伪指令 伪指令是用于告诉汇编程序如何进行汇编的指令 它不控制机器的操作也不能被汇编成机器码 只为汇编程序所识别并指导汇编如何进行 MCS 51系列单片机的常用伪指令如下 1 ORG起始地址定义伪指令格式 ORG16位地址功能 规定目标程序在程序存储器中所占空间的起始地址 例如 ORG1000H表示后面的数据或程序存放在从1000H开始的程序存储单元中 2 END汇编程序结束伪指令格式 END功能 标志源程序的结束 即通知汇编程序不再继续向下汇编 3 EQU宏代换伪指令格式 符号EQU字符串功能 在程序中用EQU后面的字符串去替换EQU前面的符号 EQU后面的字符串可以是符号 数据地址 代码地址或位地址 说明 EQU伪指令所定义的符号必须先定义后使用 所以该语句一般放在程序开始 例如 BUFFEREQU58H BUFFER的值为58HMOVA BUFFER 表示内部RAM58H单元中数据送给累加器A4 DATA数值赋值伪指令格式 符号名称DATA表达式功能 将表达式指定的数据地址或代码地址赋予符号名称 说明 DATA伪指令功能与EQU伪指令相似 但是DATA所定义的符号可以先使用后定义 该语句一般放在程序开始或结尾 例如 BUFFERDATA58H BUFFER的值为58HMOVA BUFFER 表示内部RAM58H单元中数据送给累加器A 5 DB字节存储伪指令格式 标号 DB8位二进制数据表功能 从指定的地址单元开始 定义若干个字节存储单元的内容 例4 1 ORG100HFIRST DB01H 02HSECO DB011B A 12以上伪指令经汇编后 程序存储器有关单元如图4 1所示 其中伪指令中的011B为二进制数 A 为字符A的ASCII码41H 12为十进制数 另外 格式中的标号为可选项 图4 1例4 1示意图 6 DW字存储伪指令格式 标号 DW16位二进制数据表功能 从指定的地址单元开始 定义若干个字存储单元的内容 例4 2 ORG100HFIRST DW01HDW1234H AB 以上伪指令经汇编后 程序存储器有关单元如图4 2所示 其中16位数据的高8位存入低地址单元 低8位存入高地址单元 格式中的标号为可选项 图4 2例4 2示意图 7 DS定义空间伪指令格式 标号 DS表达式功能 从指定的地址单元开始 保留由表达式指定的若干字节空间作为备用空间 例如 ORG1000HDS0AHDB12H B 伪指令汇编后从1000H单元开始 保留10个字节 从100AH开始连续存放12H 42H 8 BIT位地址符号伪指令格式 字符名称BIT位地址功能 用规定的字符名称表示位地址 例如 X0BITP1 0X1BIT30H经汇编后 P1口的第0位地址赋给X0 位地址30H赋给X1 在程序中可以分别用X0 X1代替P1 0和位地址30H 4 3简单程序设计 4 3 1顺序程序设计顺序结构的程序 是指程序按指令的排列顺序依次执行直至程序结束 这种结构是程序结构中最简单的一种 用程序流程图表示的顺序结构程序 是一个处理框紧接一个处理框 例4 3 例4 4 例4 5 见教材P80 81页 4 3 2分支程序设计分支程序是按照给定的条件进行判断 根据不同的情况使程序发生转移 选择不同的程序入口 通常用条件转移指令形成简单分支结构 例如 判断结果是否为0 JZ JNZ 是否有进位或借位 JC JNC 指定位是否为1 JB JNB 比较指令CJNE等都可作为分支依据 例4 6 例4 7 见教材P82 83页 4 4循环程序设计 4 4 1循环结构顺序程序中每条指令只执行一次 分支程序则依据条件不同会跳过一些指令 执行另一部分指令 这两种程序的特点是每条指令最多只执行一次 在处理实际问题时 常常要求某些程序段重复执行 此时应采用循环结构实现 典型的循环结构如图4 4所示 一般包含程序初始化 循环处理 循环控制和循环结束四部分 1 初始化部分为实现程序循环做准备 如建立循环计数器 设地址指针以及为变量赋初值等 2 循环处理部分该部分是循环程序的主体 在这里对数据进行实际的处理 是重复执行部分 所以这段程序的设计非常关键 应充分考虑程序的效率 3 循环控制部分为下一次数据处理而修改计数器和地址指针 并判断循环是否结束 4 结束部分分析 处理或存放结果 4 4 2单重循环程序设计1 循环次数已知的循环程序 例4 8 从60H单元开始的连续单元中有一个无符号数的数据块 其长度在5FH中 编程求数据块的最大值 存入5EH单元 分析 假设累加器A中有最大值00H 然后逐个取出数据块中的数据与之进行比较 如果当前数据大于累加器A的数据 则把数据块中的数据送给累加器A 图4 4例4 8程序流程图 否则累加器A的内容不变 即保证累加器A中存放的是每次比较出的较大数 如此循环 直至比较完最后一个数 累加器A中存放的便是所有数据中的最大值 程序流程如图4 4所示 源程序 ORG1000HCLRAMOVB 5FHMOVR0 60HLOOP CLRCSUBBA R0JCL1 ADDA R0SJMPL2L1 XCHA R0L2 INCR0DJNZB LOOPMOV5EH ASJMP END 例4 9 编程确定一个数据块中负元素的个数 假设数据块的长度存放在内部RAM51H单元 数据块从内部RAM52H单元开始存放 要求将负元素的个数存放在50H单元中 分析 判断有符号数值的正负可以通过判断该数值的最高位来完成 如果最高位为1 则该数为负 否则该数为正 另外 统计负数个数 需要在程序初始化时将存放负元素个数的单元清零 以便在循环中进行个数累计 流程图如图4 5所示 源程序 ORG1000HMOVR0 52HMOVR2 00HMOVB 51HLOOP MOVA R0JNBAcc 7 NEXTINCR2 图4 5例4 9程序流程图 NEXT INCR0DJNZB LOOPMOV50H R2SJMP END2 循环次数未知的循环程序 例4 10 从60H单元开始的连续单元中有一个无符号数0FH 编程求该数据的地址并存入5FH单元 分析 先取出60H单元的数据与立即数0FH比较 如果不相等 再取下一个单元数据进行比较 如此循环 直到两个数据相等时 记录数据地址 退出循环 判断两数是否相等有多种方法 在此我们选择两数异或指令 如果两数相等 则异或结果为0 否则结果为1 程序流程图如图4 6所示 源程序 ORG1000HMOVR0 5FHLOOP INCR0MOVA R0XRLA 0FHJZNEXTSJMPLOOPNEXT MOV5FH R0SJMP END 图4 6例4 10程序流程图 例4 11 用80C51单片机的P1口作输出 经驱动电路接8只发光二极管 如图4 7所示 当输出位是 1 时 发光二极管被点亮 输出位是 0 时二极管熄灭 编制单灯循环亮程序 即按P1 0 P1 1 P1 2 P1 6 P1 7 P1 0 P1 1 顺序 每次只有一只二极管亮 分析 要使每个灯轮流被点亮 必须在P1口的各位按指定顺序轮流输出 1 其余位输出0 可以采用循环移位指令完成 8个灯一轮的渐次点亮由循环体完成 然后利用无条件转移指令反复执行循环体 图4 7单灯循环电路图 程序流程图如图4 8所示 源程序 ORG1000HMOVA 01HLOOP MOVP1 ARLA 累加器A左循环一位LCALLDELAY 调用延时子程序SJMPLOOPDELAY MOVR2 0FAH 延时子程序L1 MOVR3 0FAHL2 DJNZR3 L2DJNZR2 L1END 图4 8例4 11程序流程图 4 4 3多重循环程序设计多重循环又称为循环嵌套 是指一个循环程序的循环体中包含另一个循环程序 理论上对循环嵌套的层数没有明确的规定 但由于受硬件资源的限制 实际可嵌套层数不能太多 需要注意的是循环嵌套只允许一个循环程序完全包含另一个循环程序 不允许两个循环程序之间相互交叉嵌套 例4 12 编程将内部RAM70H 79H中10个无符号数按由大到小的顺序排序 排序后仍存放在70H 79H中 分析 排序方法有多种 本例题采用 冒泡 法完成 具体思路是 从低地址到高地址将相邻两个单元进行比较 若低地址的内容大于相邻高地址单元的内容 则保持原状 若低地址的内容小于相邻高地址单元的内容 则两单元内容互换 图4 9给出设标志位冒泡法排序流程图 设标志位冒泡法排序源程序 ORG1000HLOOP MOVR0 70HMOVB 09HCLR10HLOOP1 MOVA R0MOV20H AINCR0MOV21H R0CJNEA 21H LOOP2 图4 9冒泡法排序流程图 LOOP2 JNCLOOP3MOVA R0MOV R0 20HDECR0MOV R0 AINCR0SETB10HLOOP3 DJNZB LOOP1JB10H LOOPSJMP END 例4 13 编写软件延时80ms程序 分析 设单片机的时钟频率为6MHz 则其机器周期为2 s 由于DJNZ指令需要2个机器周期 因此它的指令周期即指令执行时间为4 s MOV和NOP指令分别为2个机器周期和1个机器周期 为了延时80ms 我们可以通过控制循环次数的方法来解决 执行两条NOP指令和1条DJNZ指令的时间是8 s 循环250次用时2000 s 即程序中第2条到第5条指令完成的功能 若想达到延时80ms的目的 只要再使用一个循环40次的DJNZ指令即可 精确计算程序运行时间的公式为 2 2 1 1 2 250 2 40 2 s 80324 s如果单片机的时钟频率为12MHz 则其机器周期为1 s 为了延时80ms 我们只要把循环次数由40修改为80就可以了 延时程序 MOV20H 40 2机器周期指令BBB1 MOV21H 250 BBB2 NOP 1机器周期指令NOPDJNZ21H BBB2 2机器周期指令DJNZ20H BBB1SJMP 4 5子程序设计 在程序设计过程中 经常会遇到在不同的程序中或同一个程序的不同地方执行同一个操作的情况 例如软件延时 代码转换等 为了缩短程序设计周期及程序长度 可以将这些程序段从源程序中分离出来单独组成一个程序模块 我们称之为子程序 在需要使用这些模块的地方可以 调用子程序 那些调用子程序的程序被称为主程序 主程序对子程序的调用是通过ACALL或LCALL指令完成的 一个主程序可以多次调用同一个子程序 也可以调用多个子程序 子程序也可调用其他子程序 称为子程序嵌套 4 5 1关于子程序的几点说明1 每个子程序的起始指令前必须定义一个标号 作为该子程序的名称 以便主程序正确的调用它 子程序通常以RET指令结束 以便正确的返回主程序 2 子程序应具有通用性 一般 子程序的操作对象通常采用寄存器或寄存器间接寻址等寻址方式 尽量避免采用立即寻址 3 子程序应保证放在存储器的任何空间都能正确运行 即具有浮动性 例如 子程序中应使用相对转移指令 避免使用绝对转移或长转移 4 进入子程序时需要把在主程序中使用并在子程序中也要使用的寄存器进行保存 并在返回主程序之前恢复原来状态 5 子程序的调用和返回指令 以及保护现场等操作均需用到堆栈 因此在程序初始化时应设置堆栈指针SP 开辟堆栈保护区 6 设计子程序时应首先确定子程序名称 确定子程序的入口参数和出口参数 确定子程序需要使用的寄存器和存储单元 确定子程序的算法 再编写源程序 4 5 2子程序的应用举例 略 4 5 3子程序的嵌套调用子程序的嵌套调用是指在一个子程序中又调用另一个子程序 对于MCS 51单片机 子程序嵌套次数一般不受限制 子程序的嵌套调用过程如图4 10所示 当主程序执行到LCALLSB01指令时 它会将断点地址M02压入堆栈 并转去执行SB01子程序 在SB01子程序中执行到LCALLSB02指令时 它会将断点地址SB12压入堆栈 并转去执行SB02子程序 SB02子程序执行到最后的RET指令时 它会从堆栈中取出断点地址SB12送给指令计数器PC 程序返回SB01子程序 SB01子程序执行到最后的RET指令时 它会从堆栈中取出断点地址M02送给指令计数器PC 程序返回主程序 继续执行 图4 10子程序嵌套示意图 4 6 1查表程序设计查表程序是指适当的组织一些表格 跟控制程序一起事先输入到单片机的程序存储器中 使用查表指令迅速获取结果数据 该类程序主要用于代码转换 算术运算等 例4 16 例4 17 见教材P91页 说明 在例4 16和例4 17中分别使用了指令MOVCA A PC和指令MOVCA A DPTR实现查表 第一条指令是以PC作为基址寄存器 A中存放偏移量 偏移量为当前的PC值到表格首地址之间的距离 两者的和为结果所在程序存储单元的地址 4 6查表及散转程序设计 该指令执行后PC仍指向下一条指令 用PC的内容作为基地址来查表 通常分为三步 1 将所查表格的项数 即在表格中的位置 送入累加器A中 2 计算偏移量data 并在MOVCA A PC指令前加上指令ADDA data 计算公式如下 偏移量 表格首地址 MOVC指令所在的地址 1 3 执行查表指令MOVCA A PC 结果存入累加器A 第二条指令是以DPTR作为基址寄存器 A与DPTR两者的和为结果所在程序存储单元的地址 用DPTR内容作为基地址来查表 通常也分为三步 1 将表格的项数 即在表格中的位置 送入累加器A中 2 将表格的首地址送入DPTR中 3 执行查表指令MOVCA A DPTR 结果存入累加器A 4 6 2散转程序设计在设计单片机应用程序时 经常遇到根据不同的输入或运算结果决定程序流向的问题 这就是散转程序 实际就是一种多分支程序 散转程序也需要一个表 但表中所列的不是普通数据 而是某些功能程序的入口地址 偏移量或转向这些功能程序的转移指令 程序的散转功能 主要依靠间接转移指令JMP A DPTR完成 1 利用转移指令表进行散转假设有一个标志单元 它的可能取值为0 1 2 的自然数 每个值对应一个处理程序 我们可以利用转移指令表 使程序根据标志单元的值转向各自的处理程序 选择与处理程序相同数目的无条件转移指令 由这些指令组成一张指令表 且第1条转移指令转向 0 标志所对应的处理程序 第2条转移指令转向 1 标志所对应的处理程序 依此类推 然后把指令表的起始地址和标志单元的值分别送数据指针DPTR和累加器A中 最后使用散转指令完成 例4 18 见教材P93页 2 利用转向地址表进行散转当转向范围比较大时 可直接使用转向地址表法 即把每个处理程序的入口地址直接放到地址表内 用查表指令从表中查找与变量值对应的处理程序的入口地址 再通过间接转移指令 使程序转向该地址指向的功能程序 例4 19 见教材P93页 3 利用 RET 指令进行散转此方法与转向地址表法基本相同 两者的惟一区别是 转向地址表法 将表中取出功能程序的入口地址直接送给数据指针 而返回指令法 则把入口地址压入堆栈进行保存 并随后便执行一条RET指令 使程序转向功能程序 例4 20 见教材P94页 4 7实用程序举例 设计单片机的应用程序 不仅要掌握几种基本结构程序的设计步骤 设计方法 还要熟悉一些常用子程序的基本功能和使用方法 4 7 1代码转换类子程序 略 4 7 2运算类子程序 略 4 7 3数据比较类子程序 略 4 7 4数据块处理类子程序 略- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机原理与接口技术 单片机 原理 接口 技术 汇编 语言程序设计
装配图网所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
关于本文