您的浏览器Javascript被禁用,需开启后体验完整功能, 请单击此处查询如何开启
网页 资讯 视频 图片 知道 贴吧 采购 地图 文库 |

第4章AT89S51汇编语言程序设计_六年级其它课程_其它课程_小学教育_教育专区

3人阅读|次下载

第4章AT89S51汇编语言程序设计_六年级其它课程_其它课程_小学教育_教育专区。第4章 AT89S51汇编语言程序设计 ? 4.1.2 汇编语言语句和格式 ? 两种基本语句:指令语句和伪指令语句。 (1)指令语句 ? 汇编语言四分段格式: 标号字段 (LABLE)


第4章 AT89S51汇编语言程序设计 ? 4.1.2 汇编语言语句和格式 ? 两种基本语句:指令语句和伪指令语句。 (1)指令语句 ? 汇编语言四分段格式: 标号字段 (LABLE) 操作码字段 (OPCODE) 操作数字段 (OPRAND) 注释字段 (COMMENT) START: MOV A,#00H ;0→A MOV R1,#10 ;10→R1 MOV R2,#00000011B ;03H→R2 LOOP: ADD A,R2 ;(A)+(R2)→A DJNZ R1,LOOP ;R1减1不为零,则跳 LOOP处 NOP HERE: SJMP HERE 2 (2)伪指令语句 又称为汇编程序控制命令。没有相应的机器代码产生。 伪指令具有控制汇编程序的输入/输出、定义数据和符号、条 件汇编、分配存储空间等功能。 1.ORG(ORiGin)汇编起始地址命令 例如: ORG 2000H START: MOV A,#00H …… 在一源程序中,可多次用ORG指令,规定不同程序段的起始地址。 地址必须由小到大排列,且不能交叉、重叠。 2. END(END of Assembly)汇编终止命令 源程序结束标志,终止源程序的汇编工作。 3.EQU(EQUate)标号赋值命令 用于给标号赋值。赋值后,标号值在整个程序有效。 例如:TEST EQU 2000H TEST=2000H,汇编时,凡是遇到TEST时,均以2000H来代替。 4.DB(Define Byte)定义数据字节命令 在程序存储器单元中定义字节数据。例如: ORG 2000H DB 30H,40H,24,"C","B" 汇编后 (2000H)=30H (2001H)=40H (2002H)=18H(十进制数24) (2003H)=43H(字符“C”的ASCII码) (2004H)=42H(字符“B”的ASCII码) 十进制数自然转换成十六进制数,字母按ASCII码存储。 5.DW(Define Word)定义数据字命令 在程序存储器单元中定义16位的数据字。例如: ORG 2000H DW 1246H,7BH,10 汇编后 (2000H)=12H ;第1个字 (2001H)=46H (2002H)=00H ;第2个字 (2003H)=7BH (2004H)=00H ;第3个字 (2005H)=0AH DB、DW和DS命令只能对程序存储器有效,不能对数据存储器使用。 6 6.DS(Define Storage)定义存储区命令 NOP 从指定地址开始,保留指定数目的字节单元作为存储区。 例如: TABEL:DS 10 表示从TABEL代表的地址开始,保留10个连续的地址单元。 例如: ORG 2000H DS 10 H 表示从2000H地址开始,保留16个连续地址单元。 7.BIT 位定义命令 用于给字符名称赋以位地址,位地址可以是绝对位地址,也 可是符号地址。例如: QA BIT P1.6 功能是把P1.6的位地址赋给变量QA。 4.2 汇编语言源程序的汇编 汇编可分为手工汇编和机器汇编两类。 4.3 AT89S51汇编语言程序设计举例 4.3.1 子程序设计 优点:程序结构简单,缩短程序设计时间,减少存储空间。 1.子程序的设计原则和应注意的问题 (1)子程序入口地址,前必须有标号。 (2)主程序是通过调用指令来实现。有两条子程序调用指令。 ①ACALL addr11。addr11指出了调用的目的地址,PC中16位地址 中的高5位不变,即只能在同一个2KB区内。 ②LCALL addr16长调用指令。 (3)子程序结构中必须用到堆栈,用来进行断点和现场的保护。 (4)子程序返回主程序时,最后一条指令必须是RET指令。 (5)子程序可以嵌套,即主程序可以调用子程序,子程序又可 以调用另外的子程序。 2.子程序的基本结构 MAIN: …… …… LCALL SUB …… …… 子程序 SUB: PUSH PSW PUSH Acc 子程序处理程序段 POP Acc POP PSW RET ;MAIN为主程序入口标号 ;调用子程序SUB ;现场保护 子程序 ;现场恢复,注意要先进后出 ;最后一条指令必须为RET 4.3.2 查表程序设计 (1)MOVC A,@A+DPTR (2)MOVC A,@A+PC 【例4-3】 设计一子程序,功能是根据累加器A中的数x(0~9之间)查x的 平方表y,根据x的值查出相应的平方y。本例中的x和y均为单字节数。 地址 子程序 Y3Y2Y1Y0 ADD A,#01H Y3Y2Y1Y0+2 MOVC A,@A+PC Y3Y2Y1Y0+3 RET Y3Y2Y1Y0+4 DB 00H,01H,04H,09H,10H DB 19H,24H,31H,40H,51H ;数0~9的平方表 如果DPTR已被使用,则在查表前必须保护DPTR,且结束后恢 复DPTR,例4-3可改成如下形式: TAB1: PUSH DPH ;保存DPH PUSH DPL ;保存DPL MOV DPTR,#TAB1 MOVC A,@A+DPTR POP DPL ;恢复DPL POP DPH ;恢复DPH RET DB 00H,01H,04H,09H,10H;平方表 DB 19H,24H,31H,40H,51H 【例4-4】有一巡回检测报警装置,需对16路(x)输入进行检测, 每路有一个最大允许值(y),为双字节数。需根据测量的路数 (x),查表找出对应该路的最大允许值(y),看输入值是否大 于最大允许值,如果大于就报警。 取路数为x(0≤x≤15),y为最大允许值,放在表格中。设进入 查表程序前,假设路数x已放于R2中,查表后该路的最大允许值y 放于R3R4中。查表程序如下: TB3: TAB3: MOV A,R2 ADD A,R2 ;(R2)*2→(A) MOV R3,A ;保存指针 ADD A,#6 ;加偏移量 MOVC A,@A+PC ;查第一字节 XCH A,R3 ADD A,#3 MOVC A,@A+PC ;查第二字节 MOV R4,A RET DW 1520,3721,42645,7580 ;最大值表 DW 3483,32657,883,9943 DW 10000,40511,6758,8931 DW 4468,5871,13284,27808 【例4-5】 以AT89S51为核心的温度控制器,温度传感器输出 的电压与温度为非线性关系,传感器输出的电压已由A/D转换为 10位二进制数。测得的不同温度下的电压值数据构成一个表,表 中温度值为y(双字节无符号数),x(双字节无符号数)为电压 值数据。设测得电压值x放入R2R3中,根据电压值x,查找对应的 温度值y,仍放入R2R3中。程序如下: LTB2: MOV DPTR,#TAB2 MOV A,R3 CLR C RLC A MOV R3,A XCH A,R2 RLC A XCH R2,A MOV R3,A ADD A,DPL ;(R2R3)+(DPTR)→(DPTR) MOV DPL,A MOV A,DPH ADDC A,R2 MOV DPH,A CLR A MOVC A,@A+DPTR MOV R2,A CLR A INC DPTR MOVC A,@A+DPTR MOV R3,A RET TAB2: DW …, … ,… ;查第一字节 ;第一字节存入R2中 ;查第二字节 ;第二字节存入R3中 ;温度值表 4.3.3 关键字查找程序设计 数据检索有两种方法,即顺序检索和对分检索。 1.顺序检索 要检索的表是无序的,检索时只能从第1项开始逐项查找,判 断所取数据是否与关键字相等。 【例4-6】 从50个字节的无序表中查找一个关键字“xxH”。 ORG 1000H MOV 30H,#xxH ;关键字xxH送30H单元 MOV R1,#50 ;查找次数送R1 MOV A,#14 ;修正值送A MOV DPTR,#TAB4 ;表首地址送DPTR LOOP: PUSH Acc MOVC A,@ A+PC CJNE A,40H,LOOP1 MOV R2,DPH MOV R3,DPL DONE: RET LOOP1: POP Acc INC A INC DPTR DJNZ R1,LOOP MOV R2,#00H MOV R3,#00H AJMP DONE TAB4: DB …,…,… ;查表结果送A ;(40H)不等于关键字则转LOOP1 ;查到关键字,把地址送R2,R3 ;修正值弹出 ;A+1→A ;修改数据指针DPTR ;R1≠0,未查完,继续查找 ;R1=0,R2和R3清0 ;表中50个数已查完 ;从子程序返回 ;50个无序数据表 2.对分检索 对分检索的前提是检索的数据表已经排好序,以便于按照对分 原则取数。 对分检索的方法:取数据表中间位置的数与关键字进行比较, 如相等,则查找结束。 如果取数大于关键字,则下次对分检索的范围是从数据区起点 到本次取数处。 如果取数小于关键字,则下次对分检索的范围是从本次取数数 据区起点到数据区终点。依此类推,逐渐缩小检索范围,减少次 数,大大提高查找速度。 4.3.4 数据极值查找程序设计 【例4-7】片内RAM中存放一批数据,查找出最大值并存放于首地址 中。设R0中存放首地址,R2中存放字节数。程序如下: MOV R2,n ;n为要比较的数据字节数 MOV A,R0 ;存首地址指针 MOV R1,A DEC R2 MOV A,@R1 LOOP: MOV R3, A DEC R1 CLR C SUBB A,@R1 ;两个数比较 JNC LOOP1 ;C=0,A中数大,跳LOOP1 MOV A,@R1 ;C=1,则大数送A SJMP LOOP2 LOOP1: MOV A,R3 LOOP2: DJNZ R2, LOOP ;是否比较结束? MOV @R0, A ;存最大数 RET 21 4.3.5 数据排序程序设计 第一次冒泡的过程是: 6、4、1、2、5、7、3 ;原始数据的排列 4、6、1、2、5、7、3 ;逆序,互换 4、1、6、2、5、7、3 ;逆序,互换 4、1、2、6、5、7、3 ;逆序,互换 4、1、2、5、6、7、3 ;逆序,互换 4、1、2、5、6、7、3 ;正序,不互换 4、1、2、5、6、3、7 ;逆序,互换,第一次冒泡结束 如此进行,各次冒泡的结果如下: 第1次冒泡结果:4、1、2、5、6、3、7 第2次冒泡结果:1、2、4、5、3、6、7 第3次冒泡结果:1、2、4、3、5、6、7 第4次冒泡结果:1、2、3、4、5、6、7 ;已完成排序 第5次冒泡结果:1、2、3、4、5、6、7 第6次冒泡结果:1、2、3、4、5、6、7 对于n个数,理论上应进行(n-1)次冒泡才能完成排序,实际上 有时不到(n-1)次就已完成排序。 例如,上面的7个数,应进行6次冒泡,但实际上第4次冒泡时就 已经完成排序。如何判定排序是否已经完成?就是看各次冒泡中 是否有互换发生,如果有,则排序还没完成;否则就表示已经排 好序。在程序设计中,常用设置互换标志的方法,用标志的状态 表示是否有互换进行。 【例4-8】一批单字节无符号数,以R0为首地址指针,R2中为字 节数,将这批数进行升序排列。程序框图如图4-2所示。 程序如下: MAIN: MOV SP,#60H MOV PSW,#00H LP03: CLR F0 ;互换标志位F0清0 MOV R0,#30H ;数据首地址 R0 MOV R2,#0AH ;字节数送入R2 DEC R2 LP02: MOV A,@R0 MOV R3,A INC R0 MOV A,@R0 ;比较大小 CLR C SUBB A,R3 JNC LP01 MOV A,R3 ; XCH A,@R0 ;两个数互换 DEC R0 XCH A,@R0 SETB F0 ;互换标志位F0置1 INC R0 LP01:DJNZ R2,LP02 JB F0,LP03 图4-2 单字节无符号数排序程序 END 24 4.3.6 分支转移程序设计 分为无条件转移和有条件转移。 无条件分支转移程序很简单,不讨论。有条件分支转移程序按 结构类型来分,又分为单分支选择结构和多分支选择结构。 1.单分支选择结构 仅有两个出口,两者选一。一般根据运算结果的状态标志,用 条件判跳指令来选择并转移。 【例4-9】 求单字节有符号数的二进制补码 正数补码是其本身,负数补码是其反码加1。应首先判被转换 数的符号,负数进行转换,正数本身即为补码。 设二进制数放在A中,其补码放回到A中,参考程序如下: CMPT: JNB Acc.7,RETURN MOV C,Acc.7 CPL A ADD A,#1 MOV Acc.7,C RETURN:RET ;(A)>0,不需转换 ;符号位保存 ;(A)求反,加1 ;符号位存在A的最高位 图4-3 求单字节有符号二进制数补码 此外,单分支选择结构还有图4-4、图4-5所示的几种形式。 图4-4 单分支选择结构2 图4-5 单分支选择结构3 2.多分支选择结构 当程序的判别部分有两个以上的出口时,为多分支选择结构。 有两种形式,如图4-6和图4-7所示。 图4-6 多分支选择结构1 图4-7 多分支选择结构2 指令系统提供了非常有用的两种多分支选择指令: 间接转移指令 JMP @A+DPTR 比较转移指令 CJNE A,direct,rel CJNE A,#data,rel CJNE Rn,#data,rel CJNE @Ri,#data,rel 间接转移指令“JMP @A+DPTR”由数据指针DPTR决定多分支 转移程序的首地址,由A的内容选择对应分支。 4条比较转移指令CJNE能对两个欲比较的单元内容进行比较, 当不相等时,程序实现相对转移;若两者相等,则顺序往下执行。 简单的分支转移程序的设计,常采用逐次比较法。缺点是程序 太长,有n种可能的情况,就需有n个判断和转移。 【例4-10】 求符号函数的值。符号函数定义如下: 1 X>0 Y= 0 X = 0 -1 X < 0 X存放在40H单元,Y存放在41H单元,如图4-6所示。 SIGNFUC: MOV A,40H CJNE A,#00H,NZEAR NZEAR: AJMP NEGT JB Acc.7, POSI MOV A,#01H POSI: NEGT: AJMP NEGT MOV A,#81H MOV 41H, A END 实际中,经常遇到图4-7的分支转移程序设计,典型例子就是 当单片机系统中的键盘按下时,就会得到一个键值,根据不同的 键值,跳向不同的键处理程序入口。此时,可用直接转移指令 (LJMP或AJMP指令)组成一个转移表,然后把该单元的内容读 入累加器A,转移表首地址放入DPTR中,再利用间接转移指令实 现分支转移。 【例4-11】 根据寄存器R2的内容,转向各个处理程序PRGX (X=0~n)。 (R2)=0,转PRG0 (R2)=1,转PRG1 …… (R2)=n,转PRGn 程序如下: JMP6: MOV DPTR,#TAB5 ;转移表首地址送DPTR MOV A,R2 ;分支转移参量送A MOV B,#03H ;乘数3送B MUL AB ;分支转移参量乘3 MOV R6, A ;乘积的低8位暂存R6 MOV A,B ;乘积的高8位送A ADD A ,DPH ;乘积的高8位加到DPH中 MOV DPH, A MOV A, R6 JMP @A+DPTR ;多分支转移选择 …… TAB5: LJMP PRG0 ;多分支转移表 LJMP PRG1 …… LJMP PRGn ;重点 R2中的分支转移参量乘3是由于长跳转指令LJMP要占3个单元。本例 程序可位于64KB程序存储器空间的任何区域。 4.3.7 循环程序设计 1.循环程序的结构 (1)循环初始化 完成循环前的准备工作。循环控制计数初值设置、地址指针起 始地址设置、为变量预置初值等。 (2)循环处理 完成实际的处理工作,反复循环执行部分,故又称循环体。 (3)循环控制 在重复执行循环体过程中,不断修改循环控制变量,直到符合 结束条件,就结束循环程序执行。 循环结束控制方法分为循环计数控制法和条件控制法。 (4)循环结束 这部分是对循环程序执行的结果进行分析、处理和存放。 2.循环结构的控制 分为循环计数控制结构和条件控制结构。 图4-8 计数循环控制结构 图4-9 条件控制结构 (1)计数循环控制结构 DJNZ Rn,rel ;以工作寄存器作控制计数器 DJNZ direct,rel ;以直接寻址单元作控制计数器 n ? 例如,计算n个数据的和,计算公式为 y ? xi 。 i ?1 图4-10 求数据和的程序框图 【例4-12】 求n个单字节无符号数xi的和,xi按i顺序存放在内RAM从 50H开始单元中,n放在R2中,和(双字节)在R3R4中。程序如下: ADD1: MOV R2,#n ;加法次数n送R2 MOV R3,#0 ;R3存放和的高8位,初始值为0 MOV R4,#0 ;R4存放和的低8位,初始值为0 MOV R0,#50H LOOP:MOV A,R4 ADD A,@R0 MOV R4,A INC R0 CLR A ADDC A,R3 MOV R3,A DJNZ R2,LOOP ;判加法循环次数是否已到? END (2)条件控制结构 【例4-13】 一串字符,依次存放在内部RAM从30H单元开始的 连续单元中,字符串以0AH为结束标志,测试字符串长度。 如果字符与“0AH”不等,则长度计数器和字符串指针都加1; 如果比较相等,则表示该字符为“0AH”,字符串结束,计数器 值就是字符串的长度。程序如下: MOV R4,#0FFH ;长度计数器初值送R4 MOV R1,#2FH ;字符串指针初值送R1 NEXT: INC R4 INC R1 CJNE @ R1,#0AH,NEXT ;比较,不等则进行下一字符比较 END 【例4-14】 50ms延时程序。 在使用12MHz晶振时,一个机器周期为1?s,执行一条DJNZ指 令的时间为2?s。 DEL: MOV R7,#200 ;本指令执行时间1?s DEL1:MOV R6,#125 ;本指令执行时间1?s DEL2:DJNZ R6,DEL2 ;指令执行1次为2?s,计 ; 125×2 ?s=250?s DJNZ R7,DEL1 ;指令执行时间2?s,本循环体 ; 执行125次 RET ;指令执行时间2?s 以上延时程序不是太精确,如把所有指令的执行时间计算在内,它的延时 时间为[1+(1+250+2)× 200+2]?s=50.603ms,如要求比较精确的延时,应对 上述程序进行修改,才能达到较为精确的延时时间。但要注意,用软件实现 延时程序,不允许有中断,否则将严重影响定时的准确性。 对于延时更长的时间,可采用多重的循环,如1s延时,可用三重循环。 ORG 0000H MOV SP,#60H MOV PSW,#00H LP01:MOV 00H,#00H MOV 08H,#00H MOV 10H,#00H MOV 18H,#00H CLR A LP10:CJNE A,#00H,LP03 SJMP LP10 LP03:MOV B,A LP13:MOV A,R0 CJNE A,#00H,LP02 SJMP LP13 LP02:MOV PSW,#08H SJMP LP06 LP06:MOV A,R0 CJNE A,#00H,LP05 LP05:MOV PSW,#10H LP07:MOV A,R0 CJNE A,#00H,LP08 SJMP LP07 LP08:MOV PSW,#18H LP09:MOV A,R0 CJNE A,#00H,LP11 SJMP LP09 LP11:CLR C MOV A,B ADD A,00H MOV 00H,A MOV A,B ADD A,08H MOV 08H,A MOV A,B ADD A,10H MOV 10H,A MOV A,B ADD A,18H MOV 18H,A LP12:SJMP LP12 END 2、用子程序求1+2+…+100=?,结果放在 ORG 0000H R3R2中。编写程序框图。 MOV SP,#60H MOV PSW,#00H LP01:MOV R2,#00H MOV R3,#00H MOV R0,#64H MOV R1,#00H INC R1 LP10:MOV A,R2 ADD A,R1 MOV R2,A MOV A,R3 ADDC A,#00H MOV R3,A INC R1 DJNZ R0,LP10 LP13:SJMP LP13 END 1、A中内容为1-10,分别用PC指针、DPTR指针求平方,结果存入 20H单元。TABLE表放在程序存储器030H开始地址。 ORG 0000H MOV DPTR,#TABLE MOVC A,@A+DPTR LP01:SJMP LP01 ORG 0100H TABLE:DB 00H, 01H,04H,09H DB 10H,19H,24H,31H DB 40H,51H,64H ORG 0000H LP01:MOV PSW,#00H MOV SP,#60H CLR C MOV A,R1 ADD A,R0 LCALL LP10 LP02:SJMP LP02 ORG 100H LP10:PUSH ACC PUSH PSW MOV PSW,#08H CLR C MOV A,R1 ADD A,R0 MOV R2,A POP PSW POP ACC RET END 3、将30H-40H单元内容从大到小排序,结果放回30H-40H。 4、编写延时1秒子程序,用主程序调延时子程序,延时10秒。
+申请认证

文档贡献者

58895 81315 3.6
文档数 浏览总量 总评分

相关文档推荐

喜欢此文档的还喜欢