390 likes | 584 Views
第九课. 复习. 4.3 汇编语言实用程序设计. 4.3.3 查表程序设计. 4.3.7 分支转移程序设计. 4.3.8 循环程序设计. 复习. 一个源程序的四个要素 子程序:形式、功能、入口参数、出口参数 子程序的调用:调用过程示意图 子程序调用及返回指令的执行过程 子程序的现场保护和参数传递 查表程序. 4.3 汇编语言实用程序设计. 一个完整的源程序必备的四个要素:. 有 ORG 0000H ,即源程序的机器码从 ROM 的 0000H 单元开始存放。
E N D
第九课 复习 4.3 汇编语言实用程序设计 4.3.3 查表程序设计 4.3.7 分支转移程序设计 4.3.8 循环程序设计
复习 • 一个源程序的四个要素 • 子程序:形式、功能、入口参数、出口参数 • 子程序的调用:调用过程示意图 • 子程序调用及返回指令的执行过程 • 子程序的现场保护和参数传递 • 查表程序
4.3 汇编语言实用程序设计 一个完整的源程序必备的四个要素: • 有ORG 0000H,即源程序的机器码从ROM的0000H单元开始存放。 • 通常源程序的存放要跳过中断向量区。实现方法:在0000H单元存放一条转移指令,转向中断向量区后的主程序的真实的入口地址,如START、MAIN等。 • 有END,告知汇编程序,你的源程序结束了。 • 源程序的主程序框架一定是一个顺序执行的无限循环的程序,运行过程必须构成一个圈;子程序与主程序相对独立。
4.3 汇编语言实用程序设计 ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV 30H, #20 MOV 40H, #50H CLR A LCALL ABC SJMP $ ABC: MOV R3, #30H ;?30H MOV R1, #40H ;?40H CLR A L1: MOV @R1,A INC R1 DJNZ R3, L1 RET END MOV 30H, #20 MOV 40H, #50H CLR A LCALL ABC 按照规则包装成.ASM
复习EQU LENG EQU 10 SUM EQU 21H BLOCK EQU 22H ORG 0000 LJMP START ORG 0030H START: CLR A MOV R7, #LENG MOV R0, #BLOCK LOOP: ADD A, @R0 INC R0 DJNZ R7, LOOP MOV SUM, A END 功能? 有错吗? SJMP $ END 包装成子程序?
LENG EQU 10 SUM EQU 21H BLOCK EQU 22H ORG 0000 LJMP START ORG 0030H START: CLR A MOV R7, #LENG MOV R0, #BLOCK LCALL LOOP SJMP $ LOOP: ADD A, @R0 INC R0 DJNZ R7, LOOP MOV SUM, A RET END
4.3 汇编语言实用程序设计 4.3.3 查表程序设计 数据补偿、修正、计算、转换等各种功能,具有程序简单、执行速度快等优点。 查表就是根据自变量x,在表格中寻找y,使y=f(x)。 首先是用DB、DW伪指令建表,把握表格中的数据的位置与x的关系。由x来表达y在程序存储器中的地址,然后用MOVC指令实现查表。例如:求x平方时的表格结构。 DB 00H,01H,04H,09H,10H DB 19H,24H,31H,40H,51H 举例:自编例1、例2、例3及课本上的例4-5、例4-6、例4-7。
4.3 汇编语言实用程序设计-查表程序设计 指令系统中给用户提供了两条极为有用的查表指令: ⑴ MOVC A,@A+DPTR ⑵ MOVC A,@A+PC 执行查表指令时,发出读程序存储器选通脉冲/PSEN。 指令“MOVC A,@A+DPTR”完成把A中的内容作为一个无符号数与DPTR中的内容相加,所得结果为某一程序存储单元的地址,然后把该地址单元中的内容送到累加器A中。 指令“MOVC A,@A+PC”以PC作为基址寄存器,PC的内容和A的内容作为无符号数,相加后所得的数作为某一程序存储单元的地址,然后把该地址单元中的内容送到累加器A中。
4.3 汇编语言实用程序设计-查表程序设计 例4-5子程序的功能为:根据累加器A中的数x(0~9之间)查x的平方表y,根据x的值查出相应的平方y。x和y均为单字节数。 地 址 子程序 Y ADD A,#01H Y+2 MOVC A,@A+PC Y+3 RET Y+4 DB 00H,01H,04H,09H,10H DB 19H,24H,31H,40H,51H 第1条指令 ADD A,#01H 的作用是加上偏移量,可以根据A的内容查出X对应的平方。 MOVC A,@A+PC的学习
4.3 汇编语言实用程序设计-查表程序设计 例1:求x的平方,x:0~9 特点:x、y均为一字节, y=f(x)在ROM中的地址是TAB1+x ABC: MOV A, R0 MOV DPTR,#TAB1 MOVC A,@A+DPTR RET ABC: MOV A, R0 PUSH DPH ;保存DPH PUSH DPL ;保存DPL MOV DPTR,#TAB1 MOVC A,@A+DPTR POP DPL ;恢复DPL POP DPH ;恢复DPH RET 堆栈指令的使用 TAB1: DB 00H,01H,04H,09H,10H DB 19H,24H,31H,40H,51H
4.3 汇编语言实用程序设计-查表程序设计 例2:求一个0~9的数是立方 特点:x为一字节、y为两字节, y=f(x)在ROM中的地址 是TAB1+2x及TAB1+2x+1 入口参数:在R0中; 出口参数:在R2、R1中,高字节在R2中 • ABC: MOV A , R0 • RL A • MOV B, A • MOV DPTR, #TAB • MOVC A, @A+DPTR • MOV R2, A • MOV A, B • INC A • MOVC A, @A+DPTR • MOV R1, A • RET • TAB: DW 0, 1, 8, 27, 64 • DW 125, 216, 343, 512, 729
4.3 汇编语言实用程序设计-查表程序设计 例4-6 例4-6在一个以MCS-51为核心的温度控制器中,温度传感器输出的电压与温度为非线性关系,传感器输出的电压已由A/D转换为10位二进制数x。根据测得的不同温度下的电压值数据构成一个表,表中放温度值y,x为电压值数据。设测得的电压值x放入R2R3中,根据电压值x,查找对应的温度值y,仍放入R2R3中。 特点:本例的x和y均为双字节无符号数。 y=f(x)在ROM中的地址 是TAB2+2x及TAB2+2x+1 入口参数:在R2R3 中; 出口参数:在R2R3 中; ***学习双字节无符号数乘2的解决方法。 读P81 例4-6
4.3 汇编语言实用程序设计-查表程序设计 例4-7 特点:x为单字节、 y均为双字节无符号数。 y=f(x)在ROM中的地址是TAB3+2x及TAB3+2x+1 入口参数:在R2 中; 出口参数:在R3R4 中; ***又一种单字节无符号数乘2的解决方法。 用MOVC A,@A+PC,偏移量的求法。 读P81 例4-7 问题:出口参数R3R4中哪个是高字节? 例4-7 设有一个巡回检测报警装置,需对16路输入进行检测,每路有一最大允许值,为双字节数。运行时,需根据测量的路数,找出每路的最大允许值。看输入值是否大于最大允许值,如大于就报警。根据上述要求,编一个查表程序。 取路数为x(0~15),y为最大允许值,事先存放在表格中。
4.3 汇编语言实用程序设计-查表程序设计 例3 编写程序,实现 。设a,b,c分别存于内部RAM的30H,31H,32H三个单元中。程序段如下: START:MOV A,30H ;取a ACALL SQR ;调用查平方表 MOV R1,A ;a2 暂存于R1中 MOV A,31H ;取b ACALL SQR ;调用查平方表 ADD A,R1 ;a2+b2 存于A中 MOV 32H,A ;存结果 SJMP $ SQR :MOV DPTR,#TAB ;子程序 MOVC A,@A+DPTR ; RET TAB :DB 0,1,4,9,16 ,25,36,49,64,81 子程序与查表的综合举例
4.3 汇编语言实用程序设计-查表程序设计 思考题 • 求 x平方,x在R0中,取值范围在5~15 ABC: MOV A, R0 MOV DPTR,#TAB1 MOVC A,@A+DPTR RET TAB1: DB 25, 36, 49, 64,81 DB 100,121,169,196,225 ABC: MOV A, R0 CLR C SUBB A, #5 MOV DPTR,#TAB1 MOVC A,@A+DPTR RET TAB1: DB 25, 36, 49, 64,81 DB 100,121,169,196,225
4.3 汇编语言实用程序设计-分支转移程序设计 4.3.7 分支转移程序设计 特点是程序中含有转移指令。 转移指令有分为无条件转移和有条件转移。 有条件分支转移程序按结构类型来分,又分为单分支转移结构和多分支转移结构。 1.单分支转移结构 程序的判别部分仅有两个出口,两者选一。 2.多分支转移结构 程序的判别部分有两个以上的出口流向。
4.3 汇编语言实用程序设计-分支转移程序设计 有条件转移指令通常可以完成单分支转移 下列两种转移指令可以完成多分支转移 间接转移指令: JMP @A+DPTR; 比较转移指令: CJNE A,direct,rel; CJNE A,#data,rel; CJNE Rn,#data,rel; CJNE @Ri,#data,rel;
例4.两个无符号数比较 例4-12 求符号函数的值。 例4-13 散转 例5 :求50H单元后30个数的累加和 例4-16 测试字符串长度的程序。 例4-17 50ms延时程序 练习:写一个延时10ms的子程序。(钟频12MHz )
4.3 汇编语言实用程序设计-分支转移程序设计 (2)分支程序设计 例4.两个无符号数比较 内部RAM的40H单元和41H单元各存放了一个8位无符号数, 请比较这两个数的大小,比较结果通过单片机对LED的控制显示出来。即: 若(40H)≥(41H),则P1.0管脚连接的LED发光; 若(40H)<(41H),则P1.1管脚连接的LED发光。
4.3 汇编语言实用程序设计-分支转移程序设计 Y 开始 (40H)-(41H) N CY=0? (40H)≥(41H) P1.0灯亮 (40H)<(41H) P1.1灯亮 流程图 结束 图 两个无符号数比较流程图
4.3 汇编语言实用程序设计-分支转移程序设计 方法1:使用SUBB指令,依据借位CY状态判断两个数的大小! ORG 1000H CLR C ;清CY为零 MOV A,40H;取第一个数送A SUBB A,41H;两数比较 JNC LED0;CY=0,转至LED0 CLR P1.1;CY=1,(40H)<(41H),点亮P1.1 LED LED0: CLR P1.0;CY=0,40H≥(41H),点亮P1.0 LED FINISH: RET SJMP FINISH ;跳转到结束
4.3 汇编语言实用程序设计-分支转移程序设计 方法2:使用CJNE指令比较,借位CY来判断两个数的大小! ORG 0000H MOV A,40H;取40H单元数据送A CJNE A,41H,COMP;两数比较 COPM: JNC LED0 ;相等后的判别 CLR P1.1;CY=1,(40)<(41H) ;点亮P1.1;连接的LED SJMP FINISH;跳转到结束 LED0: CLR P1.0;CY=0,40H≥(41H), ;点亮P1.0连接的LED FINISH: SJMP $ END
4.3 汇编语言实用程序设计-分支转移程序设计 例4-12求符号函数的值。程序框图如图4-6所示。 数据规划:X放40H Y放41H 用CJNE指令,借助于CY,可以判别X的符号。
4.3 汇编语言实用程序设计-分支转移程序设计 读P89,注意其中的转移指令AJMP NEGT 练习题: 设变量 x 以补码的形式存放在片内RAM的30H单元,变量 y 与 x 的关系是:当 x 大于0时,y =x;当 x =0时,y =20H;当 x 小于0时,y =x+5。编制程序,根据 x 的大小求y并送回原单元。
4.3 汇编语言实用程序设计-分支转移程序设计 多分支转移结构 典型的例子 当单片机系统中的键盘按下时,就会得到一个键值,根据不同的键值,跳向不同的键处理程序入口。 根据某一单元的内容是0,1,……,n,来分别转向处理程序0,处理程序1,……处理程序n。 对于这种情况,可用直接转移指令(LJMP或AJMP指令)组成一个地址转移表,然后把该单元的内容(键值)读入累加器A(?),地址转移表首地址放入DPTR中,再利用间接转移指令(JMP @A+DPTR)实现分支转移。
4.3 汇编语言实用程序设计-分支转移程序设计 例4-13根据寄存器R2的内容,转向各个处理程序PRGx (x=0~n) (R2)=0,转PRG0 (R2)=1,转PRG1 ┇ (R2)=n, 转PRGn JMP6: MOV DPTR, #TAB6 MOV A, R2 MOV B, #03 ; MUL AB JMP @A+DPTR TAB6: LJMP PRG0 LJMP PRG1 地址转移表
4.3 汇编语言实用程序设计 4.3.8 循环程序设计 优点:(1)可大大缩短程序长度 (2)使程序所占的内存单元数量少 (3)使程序结构紧凑和可读性变好。 一、循环程序的结构 循环结构程序主要由以下四部分组成。 1.循环初始化 2.循环处理 3.循环控制 4.循环结束
4.3 汇编语言实用程序设计-循环程序设计 1.循环初始化 循环初始化程序段用于完成循环前的的准备工作。例如,循环控制计数初值的设置、地址指针的起始地址的设置、为变量预置初值等。 2.循环处理 循环程序结构的核心部分,完成实际的处理工作,是需反复循环执行的部分,故又称循环体。这部分程序的内容,取决于实际处理问题的本身 3.循环控制 在重复执行循环体的过程中,不断修改循环控制变量,直到符合结束条件,就结束循环程序的执行。循环结束控制方法分为循环计数控制法和条件控制法 4.循环结束 这部分是对循环程序执行的结果进行分析、处理和存放。
4.3 汇编语言实用程序设计-循环程序设计 直到型 当性 二、循环结构的控制 图4-8是计数循环控制结构,图4-9是条件控制结构。
4.3 汇编语言实用程序设计-循环程序设计 1.计数循环结构 计数控制方法只有在循环次数已知的情况下才适用。 计数循环控制结构是依据计数器的值来决定循环次数,一般为减“1” 计数器,计数器减到“0”时,结束循环。计数器的初值是在初始化时设定。 MCS-51的指令系统提供了功能极强的循环控制指令: DJNZ Rn, rel;工作寄存器作控制计数器 DJNZ direct,rel;以直接寻址单元作控制计数器 例如,计算n个数据的和。 程序框图见图4-10 。P92
4.3 汇编语言实用程序设计-循环程序设计 例5 :求50H单元后30个数的累加和,放入B ABC: MOV R7,#30 MOV R0,#50H CLR A LOOP: ADD A,@R0 INC R0 DJNZ R7,LOOP MOV B,A RET 初始化 循环体 循环结束 如果结果有进位,怎么办?见P93
4.3 汇编语言实用程序设计-循环程序设计 2.条件控制结构 例4-16设有一串字符,依次存放在内部RAM从30H单元开始的连续单元中,该字符串以0AH为结束标志,编写测试字符串长度的程序。 本例采用逐个字符依次与“0AH”比较的方法。为此设置一个长度计数器和一个字符串指针。长度计数器用来累计字符串的长度,字符串指针用于指定字符。如果指定字符与“0AH”不相等,则长度计数器和字符串指针都加1,以便继续往下比较;如果比较相等,则表示该字符为“0AH”,字符串结束,长度计数器的值就是字符串的长度。程序见P93。
4.3 汇编语言实用程序设计-循环程序设计 3.多重循环 例4-17 50ms延时程序。 延时程序与MCS-51指令执行时间有很大的关系。在使用12MHz晶振时,一个机器周期为1µs,执行一条DJNZ指令的时间为2µs。这时,可用双重循环方法写出下面如下的延时50ms的程序: DEL: MOV R7,#200 DEL1: MOV R6,#125 DEL2: DJNZ R6,DEL2 ;125*2=250µs DJNZ R7,DEL1 ;0.25ms*200=50ms RET
4.3 汇编语言实用程序设计-循环程序设计 125 ①→ ②→ ③→ ④→⑤ 200 机器周期T=1μS △t= [ 1+200(1+2*125+2)+2]*T = 50603*T = 50.603mS
4.3 汇编语言实用程序设计-循环程序设计 如果要求比较精确的延时,可按如下修改: DEL: MOV R7,#200 DEL1: MOV R6,#123 NOP DEL2: DJNZ R6,DEL2 ;2*123+2=248µs DJNZ R7,DEL1 ;(248+2)*200+1=50.001ms RET △t= [ 1+200(1+1+2*123+2)+2]*T = 50003*T = 50.003mS 注意: 软件延时程序,不允许有中断,否则将严重影响定时的准确性。
4.3 汇编语言实用程序设计-循环程序设计 练习: • 写一个延时10ms的子程序。(近似值,钟频12MHz) • 写一个延时1s的子程序。 DEL10: MOV R7,#200 DEL1: MOV R6,#25 DEL2: DJNZ R6,DEL2 ;25*2=50µs DJNZ R7,DEL1 ;0.05ms*200=10ms RET DEL1S: MOV R5, #100 LLL: ACALL DEL10 DJNZ R5, LLL RET 九结束