430 likes | 574 Views
简单程序. 查表程序. 子程序. 分支程序. 循环程序. 第四章 汇编语言程序设计. 程序设计实例引入. 实例 假设一个班有50个人, 共有3门选修课: 计算机算法 服装 CAD 设计 德语 请找出: 同时选了三门课的同学;. 计算机算法. 服装 CAD 设计. 德语. 5. 2. 4. 12. 25. 12. 23. 39. 25. 25. 29. 29. 39. 39. 问题的解决. 第一步 如何在计算机中表示选修某门课的所有同学 ?. 选修这门人数. 学生的学号. 这个过程实际上是设计数据结构的问题.
E N D
简单程序 查表程序 子程序 分支程序 循环程序 第四章 汇编语言程序设计
程序设计实例引入 • 实例 假设一个班有50个人, 共有3门选修课: • 计算机算法 • 服装CAD设计 • 德语 请找出: • 同时选了三门课的同学;
计算机算法 服装CAD设计 德语 5 2 4 12 25 12 23 39 25 25 29 29 39 39 问题的解决 • 第一步 如何在计算机中表示选修某门课的所有同学? 选修这门人数 学生的学号 这个过程实际上是设计数据结构的问题
计算机算法 CAD设计 德语 问题的解决 • 第二步 设计思路:找出同时选了三门课的同学 这个过程实际上是设计算法的过程,既构建模型。
找出第一个学生 N 他选计算机吗? Y N 他选了德语吗? Y N 他选了CAD吗? Y 记录要找的人 N 还有学生吗? Y 结束 下一个学生 第三步:设计流程 重复该过程
几点启示 • 整体构思; • 构建整体流程框图; • 结构合理,流程清晰,简单明了; • 局部模块化;
为什么要用流程图? • 符合人进行逻辑思考的习惯 • 计算机从根本上来说,没有任何逻辑性,所以,你必须告诉它,先做什么,后做什么,遇到什么情况又该做什么,等等 • 流程图设计本身是一个逐步求精的过程,最终将任务划分为若干能由机器指令实现的小模块
4.1 程序设计过程 • 题意分析 • 画出流程图 • 分配内存及端口 • 编制源程序 • 仿真、调试程序 • 固化程序
2、编程技巧 • 程序功能模块化 • 尽量采用循环结构和子程序 • 少用无条件转移指令 • 多采用累加器来传递参数 • 注意现场保护,即压入堆栈
4.2 顺序程序设计 例:求多项式 a2-b 解:设a存放在R2中,b存放在R3中,结果存放在R6和R7中。 程序如下: MOV A, R2 MOV B, A MUL AB CLR C SUBB A, R3 ;带进位减 MOV R7,A :保存低8位 MOV A, B SUBB A,#00H ;高八位减进位 MOV R6,A END
4.3 分支程序设计 • 根据不同的条件转向不同的处理程序 • 控制转移指令 AJMP、LJMP、SJMP 、JMP JZ、JNZ、CJNE、DJNZ • 位转移指令 JC、JNC、JB、JNB、JBC
START 0C (A)-30HA (A) < 10 ? (A)-7 A END 举例;累加器A内有一个16进制ASCII字符,要求转换成一个16进制数存放于A。 ASCII字符转换成16进制数规则: 数字0~9 :只需减30H 字母A~F :减30H,再减7 ASCH: CLR C SUBB A, #30 CJNEA, #10, $+3 JC AH10 SUBB A, #07 AH10: RET
散转程序—多分支程序 • 散转程序是指通过修改某个参数后,程序可以有三个以上的流向,多用于键盘程序。 • 常用的指令是JMP @A+DPTR A中内容为8位无符号数 16位地址数 + DPTR A PC
例: 根据R7的内容,转向各自对应的操作程序(R7= 0,转入OPR0;R7= 1,转入OPR1…R7= n,转入OPRn) 程序清单如下: JUMP1: MOV DPTR,#JPTAB1 ;跳转表首送数据指针 MOV A,R7 ADD A,R7 ;R72A (修正变址值) JNC NOAD ;判有否进位 INC DPH ;有进位则加到高字节地址 NOAD: JMP @A+DPTR ;转向形成的散转地址人口 JPTAB1: AJMP OPR0 ;直接转移地址表 AJMP OPR1 . AJMP OPRn
K=? 分支程序0 分支程序1 分支程序n
4.4 循环程序设计 • 循环程序的结构 • 置循环初值 • 循环体 • 修改控制变量 • 循环终止控制
例:设在外部RAM中有一个ASCII字符串,它的首地址是在DPTR中,字符串以‘0’结束。现要求用89c51串行口把该字符串发送出去。在串行口已经初始化的条件下,该流程图可用以下框图表示:例:设在外部RAM中有一个ASCII字符串,它的首地址是在DPTR中,字符串以‘0’结束。现要求用89c51串行口把该字符串发送出去。在串行口已经初始化的条件下,该流程图可用以下框图表示: 循环程序举例 TI:串口发送中断请求标志。每发送完串行数据,硬件自动将TI置1。CPU响应中断后,须由软件清0
开始 ((DPTR))->A (A)=0? 发送器空? 0->TI (A) ->SBUF (DPTR)+1->DPTR • 流程图 结束
程序:SOUT: MOVX A,@DPTR JNZ SOT1 RET SOT1: JNB TI,SOT1 CLR TI MOV SBUF,A INC DPTR SJMP SOUT TI:串口发送中断请求标志。每发送完串行数据,硬件自动将 TI置1。CPU响应中断后,须由软件清0
例:200名学生参加考试,成绩放在8031的外部RAM的一个连续存储单元,95~100分颁发A级证书,90~94分颁发B级证书,编一程序,统计获A、B级证书的人数。将结果存入内部RAM的两个单元。例:200名学生参加考试,成绩放在8031的外部RAM的一个连续存储单元,95~100分颁发A级证书,90~94分颁发B级证书,编一程序,统计获A、B级证书的人数。将结果存入内部RAM的两个单元。
ORG 0030H EG XDATA 1000H GA DATA 20H GB DATA 21H MOV GA,#00 MOV GB,#00 MOV DPTR,#EG MOV R2,#200 LOOP:MOVX A,@DPTR CJNE A,#95, LOOP1 LOOP1: JNC NEXT1 CJNE A,#90,LOOP2 LOOP2: JC NEXT INC GB SJMP NEXT NEXT1: INC GA NEXT: INC DPTR DJNZ R2,LOOP SJMP $ END
4.5 查表程序 • 表格是事先存放在ROM中的,一般为一串有序的常数,例如平方表、字型码表等。 • 表格可通过伪指令DB来确定。 • 通过查表指令MOVC A,@A+DPTR MOVC A,@A+PC来实现。 • 用DB、DW建立表格 • 首地址送DPTR • 关键字送A • 查表:MOVC A,@A+DPTR
用查表法计算平方(一) ORG 0000H MOV DPTR,#TABLE ;表首地址送DPTR MOV A,#05 ;被查数字05A MOVC A,@A+DPTR ;查表求平方 SJMP $ TABLE:DB 0,1,4,9,16,25,36,49,64,81 END
用查表法计算平方(二) ORG 0000H 0000H MOV A,#05 ;05 A 0002H ADD A,#02 ;修正累加器A 0004H MOVC A,@A+PC ;查表求平方 0005H SJMP $ 0007H: DB 0,1,4,9,16,25,36,49,64,81 END
使用 MOVC A,@A+PC须注意: 1.使用传送指令将关键字送入ACC 2.ADD A, #DATA指令对A进行修改: PC+DATA=表格首地址 3.MOVC A,@A+PC 完成查表. DATA=表格首地址-指令地址-1
例: • MOV A, X • ADD A,#01H • MOVC A,@A+PC • RET • DB 00,01,04,09,10H,19H,24H,31H,30H… DATA=表格首地址-指令地址-1 即:MOVC与DB之间的字节数
4.7 子程序设计 • 好处: • 避免重复编程 • 简化程序的逻辑结构 • 缩短程序长度,节省存储单元 • 便于调试、增强可移植性
1、子程序编写注意的问题 2k范围内 64k范围内 • 子程序调用: ACALL、 LCALL • 子程序返回: RET • 子程序第一条必须有标号. • 注意现场的保护和恢复 • 子程序嵌套注意的问题:嵌套深度与堆栈区大小的问题. • 正确传递参数: 入口参数和出口参数.
2、 参数传递方法 • 用累加器或工作寄存器来传递参数 • 用指针寄存器来传递参数 • 用堆栈来传递参数 • 程序段参数传递(适于传递大量常数参数)
(1)累加器或工作寄存器传递参数 • A、R0~R7 • 优点:最简单,运算速度快。 • 缺点:累加器和工作寄存器数量有限,不能传递太多参数。
(2)指针寄存器传递参数 片内RAM:@R0、@R1 片外RAM:@DPTR 例:将(R0)和(R1)指出的内部RAM中两个3B无符号整数相加,结果送(R0)指出的内部RAM中,入口时, (R0)(R1)分别指向加数和被加数的低字节,出口时,(R0)指向结果的高位字节。利用MCS-51的带进位加法指令,编写程序:
程序: NADD: MOV R7,#3 CLR C NADD1: MOV A,@R0 ADDC A,@R1 MOV @R0,A INC R0 INC R1 DJNE R7,NADD1 JNC ADDB MOV @R0,#01H ADDB: DEC R0 RET
(3)堆栈传递参数 • PUSH • POP 优点:简单,能传递大量参数,由于参数在堆栈中,故大大简化了中断响应时的现场保护。
(4)程序段参数传递 • 采用程序段参数传递的方法,编写字符串发送的子程序: SOUT: POP DPH POP DPL SOT1:CLR A MOVC A,@A+DPTR INC DPTR JZ SEND JNB TI ,$ CLR TI MOV SBUF,A SJMP SOT1 SEND: JMP @A+DPTR
以发送‘MCS-51 CONTROLLER ’为例,说明该子程序的调用方法: • ACALL SOUT DB ‘MCS-51 CONTROLLER ’ DB 0AH,0DH,0 换行键 回车键 • 以上子程序特点: • 不以一般返回指令RET结尾,而是采用散转指令返回到参数表后第一条指令 • 可适用ACALL或LCALL,因为这两种调用指令把下一条指令或数据字节地址压入堆栈 • 需传递的参数可按最方便的次序排列 • 子程序只使用A和DPTR
习题1: 片内RAM中30H和31H中存有两个无符号数,将两个数的最小者存放入40H中。
开始 (30H)->A Y (30H)=(31H)? N 存 任 意 数 (30H)>(31H)? N Y (30H)40H (31H)40H 结束 解:1)需要用到的指令:CJNE、JC 2) 画流程图 3)编程 ORG 1000H MOV A,30H CJNE A,31H,BIG SJMP STORE BIG: JC STORE MOV A,31H STORE:MOV 40H,A END
习题2 设变量X存放在VAR单元内,函数Y存放在FUNC单元内,按下式赋值: 1 X>0 Y = 0 X=0 -1 X<1
开始 • 解:1)假设VAR在片内RAM的30H单元,FUNC在片内RAM的31H单元; 2)画流程图 (VAR)A Y A=0? 0(31H) A>0? Y 1(31H) -1(31H) 结束
3)编程 ORG 2000H 30H DATA VAR 31H DATA FUNC START:MOV A,30H JZ COMP JNB ACC.7,POSI MOV 31H,#0FFH POSI: MOV 31H,#01H COMP: MOV 31H,#00H END
习题3: 设计延时50ms的程序,设晶振为12MHz。
解:1机器周期=1us (T=1/f×12) 延时用DJNZ-----2个机器周期 50ms = 2us×125×200 编程:DEL: MOV R7,#200 DEL1:MOV R6,#125 DEL2:DJNZ R6,DEL2 DJNE R7,DEL1 RET 实际上,该程序执行时间>50ms,因为没有考虑到除DJNZ指令之外的其它指令的执行时间。
例设一巡回报警系统,对16路输入进行控制,现根据测量路数,找出每路的最大允许值。(若大于允许值就报警)。(查找双字节表格)例设一巡回报警系统,对16路输入进行控制,现根据测量路数,找出每路的最大允许值。(若大于允许值就报警)。(查找双字节表格) TB3: MOV A,R2 ADD A,R2 MOV R3,A ADD A, #6 MOVC A,@A+PC XCH A,R3 ADD A, #3 MOVC A,@A+PC MOV R4,A RET TAB3: DW 1520,3721,4256 ; 表格最大长度256 DW …