480 likes | 641 Views
第 4 章 汇编语言程序设计知识. 4.1.1 汇编语言及其语句格式 1 、汇编语言 这里介绍 MCS-51 单片机的汇编语言。 2 、汇编语言的语句格式 一条汇编语言的语句包括四部分内容:标号、操作码、操作数和注释。其格式为: 标号:操作码 操作数;注释 例如: LOOP: MOV A , #20H ; (A)←20H. 4.1 汇编语言程序设计. 1 、定位伪指令 格式: ORG n 2 、定义字节伪指令 格式:标号: DB X1, X2, ……Xn
E N D
4.1.1 汇编语言及其语句格式 1、汇编语言 这里介绍MCS-51单片机的汇编语言。 2、汇编语言的语句格式 一条汇编语言的语句包括四部分内容:标号、操作码、操作数和注释。其格式为: 标号:操作码 操作数;注释 例如:LOOP: MOV A , #20H ; (A)←20H 4.1 汇编语言程序设计
1、定位伪指令 格式:ORG n 2、定义字节伪指令 格式:标号:DB X1, X2, ……Xn 此伪指令的功能是把Xi存入从标号开始连续的单元中。 3、定义字伪指令 格式:标号:DW X1,X2,……Xn 此伪指令的功能是把Xi存入从标号开始的连续单元中。 4.1.2 伪指令 思考:伪指令的作用?
4、预留存贮区伪指令 格式:DS n DS n从标号指定单元开始,预留n个单元的存贮区。 注:DB,DW,DS伪指令都只对程序存储器起作用,不能对数据存储器进行初始化 5、赋值伪指令 格式:字符名称 EQU n 此指令的功能是将数据或地址n赋给字符名称。
6、DATA 数据地址赋值命令 格式:字符名称 DATA 表达式 注:功能与EQU类似,但有区别 (1)EQU伪指令可以把一个汇编符号赋给一个名字,而DATA只能把数据赋给字符名 (2)用EQU必须先定义后使用,DATA定义的符号名可以后定义先使用 (3)DATA可以把一个表达式的值赋给字符名称,其中的表达式应是可求值的
7、结束汇编指令 格式: END END指示源程序到结束,常将其放在汇编语言源程序的末尾。 8、BIT 位地址符号命令 格式:符号名 BIT 位地址
1、分析任务,确定算法或解题思路 2、根据算法和解决思路画出程序流程图 流程图是由一些框图和流程线组合而成: 4.1.3 汇编语言程序设计过程 通过流程图把具有一定功能的各部分有机的联系起来。
3、根据流程图编写程序 4、上机调试程序
4. 2. 1 顺序结构程序设计 按照程序编写的顺序,依次执行。任何复杂的程序,都含有较大成份的顺序结构程序。 【例4-1】 将两位压缩BCD码转换成二进制数 编程思路:(a1a0)BCD= a1×10+a0 编程说明:待转换的两位压缩BCD码存放于R2,转换结果存回R2。 程序流程图如图4-1所示。 4.2 汇编程序结构
编程如下: START: MOV A , R2 ANL A , #0F0H ;取高位BCD码 SWAP A MOV B , #0AH MUL AB MOV R3 , A MOV A , R2 ANL A , #0FH ;取低位BCD码 ADD A , R3 MOV R2 , A END
【例4-2】 求符号函数的值 1 当X>0 Y= 0 当X=0 的值。 -1 当X<0 编程说明:设变量X存放在40H单元中,函数Y存放在41H单元中。此程序为三分支程序。 程序流程图如图4-2所示。
编程如下: START: MOV A,40H JZ COMP JNB ACC.7, POST MOV A,#81H ;表示-1 SJMP COMP POST: MOV A,#01H ;表示+1 COMP: MOV 41H,A END
CJNE A,55H,LOOPH AJMP FH LOOPH: JNC JW CJNE A,54H,LOOP2 AJMP FH LOOP2: JC SW FH: RET JW: …. ;降温处理 SW: …. ;升温处理 例4-3 使用多条CJNE实现多分支程序转移某温度控制系统,采集的温度值(Ta)放在A中,此外,在内部RAM 54h单元存放控制温度的下限值(T54),在55h单元中存放控制温度的上限(T55),若Ta>T55,程序转向JW(降温处理),若Ta<T54,程序转向SW(升温处理),否则,转向FH(返回主程序).
例4-4: 使用查表地址方法实现多分支程序转移 有BR0,BR1,BR2和BR3共4个分支程序,各分支程序的功能是依次从内部RAM取数,外部低256B Ram取数,外部4kb取数,外部64KB取数。 R3:入口参数(0~3),选择取数存储区。 R0:存储器低8位地址。 R1:存储器高8位地址。
MOV A,R3 MOV DPTR,#BRTAB MOVC A,@A+DPTR JMP @A+DPTR BRTAB:DB BR0-BRTAB ;存放差值 DB BR1-BRTAB DB BR2-BRTAB DB BR3-BRTAB BR0: MOV A,@R0 SJMP BRE BR1: MOVX A,@R0 SJMP BRE BR2: MOV A,R1 ANL A,#0FH ANL P2,#0F0H ORL P2,A MOVX A,@ R0 SJMP BRE BR3: MOV DPL,R0 MOV DPH,R1 MOVX A,@DPTR BRE: SJMP $
…… MOV DPTR,#3000H CLR C RLC A JMP @A+DPTR 3000H 3001H 3002H AJMP DS ;转到读数据程序 3003H 3004H AJMP XS ;转到写数据程序 3005H 3006H AJMP CR ;转到插入程序 例4-5:使用查表转移指令实现多分支程序设键盘上有3个操作键 键值:01 功能:读数据 键值:02 功能:写数据 键值:03 功能:插入假定键值放在A中
MOV DPTR,#BRTAB MOV A,R3 RL A MOV R1,A INC A MOVC A,@A+DPTR PUSH ACC ;先压低八位地址 MOV A,R1 MOVC A,@A+DPTR PUSH ACC ;再压高八位地址 RET BRTAB: DW BR0 DW BR1 ….. DW BR127 例4-6:通过堆栈操作实现多分支转移程序。分支程序入口地址存在BRTAB表中,并假定分支转移序号值在R3中
例 4-7 散转程序设计 K=? K=0 转向n-1分支 转向n分支 转向0分支 转向1分支 …… 图中,K的最大值一般为128。 设寄存器R3中存有分支转移序号00H~7FH,试编写根据序号转移的程序。
JMP_128: MOV A, R3 RL A MOV DPTR, #JMPTAB JMP @A+DPTR JMPTAB: AJMP ROUT00 ; 128个子程序首址 AJMP ROUT01 … … AJMP ROUT7F 说明: 此程序要求转移目的地址ROUT00~ ROUT7F必须驻留在与指令AJMP同一个2KB存储区内,且程序的最大分支值为128。
【例4-8】已知内存单元有16个二进制无符号数,分别存放在30H~3FH中,试求它们的累加和,并将其和数存放在R4、R5中。【例4-8】已知内存单元有16个二进制无符号数,分别存放在30H~3FH中,试求它们的累加和,并将其和数存放在R4、R5中。 编程说明:存放16个二进制无符号数的首地址为30H,此循环程序的循环次数为16次,和数放在R4(高位)、R5(低位)中。程序流程如图。
参考程序如下: START: MOV R0 ,#30H MOV R2 , #10H MOV R4 , #00H MOV R5 , #00H LOOP: MOV A , R5 ADD A , @R0 MOV R5 , A MOV A , #00H ADDC A , R4 MOV R4 , A INC R0 DJNZ R2 , LOOP END
4.2.4 查表程序设计 【例4-9】利用查表的方法编写Y= X2 (X=0,1,2…9 )的程序。 编程说明:设变量X的值存放在内存30H单元中,变量Y的值存入内存31H单元。先用远查表指令MOVC A, @A+DPTR 编写程序(参考程序1);再用近查表指令MOVC A , @A+PC 编写程序(见参考程序2)。
参考程序1: ORG 1000H START: MOV A , 30H MOV DPTR , #TABLE MOVC A , @A+DPTR MOV 31H , A TABLE: DB 0 , 1 , 4 , 9 , 16 DB 25 , 36 , 49 , 64 , 81 END
参考程序2: ORG 1000H START: MOV A , 30H ADD A , 02H;思考该指令的作用? MOVC A , @A+PC MOV 31H , A DB 0 , 1 , 4 , 9 , 16 DB 25 , 36 , 49 , 64 , 81 END
【例4-10】将1位十六进制数,转换成相应ASCⅡ码。用计算求解和查表求解,进行比较。【例4-10】将1位十六进制数,转换成相应ASCⅡ码。用计算求解和查表求解,进行比较。 (1)计算求解: 编程说明: 设待转换的一位十六进制数存放在40H 单元中,转换后的ASCⅡ码仍存放在40H 中。 编程思路: 十六进制数0~9 的ASCⅡ为41H~46H,当待转换的数≤9时,加30H,既是其对应的ASCⅡ码;当待转换的数>9时,加37H。程序流程如图所示。
参考程序如下: ORG 0100 H MOV A , 40 H ANL A , # 0F H CLR C SUBB A, # 0AH ;A<10? JC NEXT ADD A , #0AH ADD A , #37H SJMP SAVE NEXT: ADD A , #0AH ADD A , #30H SAVE: MOV 40H , A END
(2) 查表求解: ORG 0100H MOV A , 40H ANL A , #0FH ADD A , 02H MOVC A , @A+PC MOV 40H , A DB ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’ DB ‘6’, ‘7’, ‘8’, ‘9’, ‘A’, ‘B’ DB ‘C’, ‘D’, ‘E’, ‘F’ END
4.2.5 子程序设计 1、子程序的调用与返回 MCS-51单片机有两条子程序调用指令:ACALL addr11、 LCALL addr16;一条子程序返回指令RET。 2、保存与恢复寄存器内容 例如:SUB1: PUSH PSW PUSH ACC PUSH 06H ∶ (此处省略了子程序的内容) ∶ POP 06H POP ACC POP PSW
3、子程序的参数传递 主程序在调用子程序时,经常需要传送一些参数,子程序运行完后也经常将一些参数回送给主程序,这叫参数传递。
用工作寄存器和累加器传递参数 【例4-11 】 编程计算c = a2 +b2。(a,b=0~9) 编程说明:这个问题中,计算某数的平方可以用子程序来实现,两次调用该子程序,并求和便得到所需结果。设a、b 分别存于内部RAM 的30H、31H单元,结果C存于内部RAM的40H单元。
参数传递:主程序中,将某数存放到累加器A中,作为子程序的入口参数;子程序中,将所求数的平方值存放在累加器A中,作为出口参数(即主程序的返回值)。参数传递:主程序中,将某数存放到累加器A中,作为子程序的入口参数;子程序中,将所求数的平方值存放在累加器A中,作为出口参数(即主程序的返回值)。 子程序的入口参数:A中存放某数的值。 子程序的出口参数:A中存放所求数的平方。子程序如下: SQR: INC A MOVC A , @A+PC ;查平方表 RET TABLE: DB 0 , 1 , 4 , 9 , 16 DB 25 , 36 , 49 , 64 , 81 主程序流程图如图 所示。
主程序如下: START: MOV A , 30H ACALL SQR ;调查表子程序 MOV R1 , A ;a2暂存R1中 MOV A , 31H ACALL SQR ;调查表子程序 ADD A , R1 MOV 40H , A END
例4-12:设计8位二进制数转换为BCD数子程序。二进制数范围:0~FFH BCD数范围:0~255 入口: (A)=二进制数 出口: (R0)=十位数和个位数地址指针 BINBCD: MOV B,#100 DIV AB ;(A)=百位数 MOV @R0,A INC R0 MOV A,#10 XCH A,B DIV AB ; (A)=十位数,(B)=个位数 SWAP A ADD A,B MOV @R0,A RET
用RAM (指针寄存器)传递参数 例4-13:(R0)和(R1)指出的RAM中的两个三字节无符号整数相加,结果送到由(R0)指出的RAM 入口:(R0),(R1)分别指出加数和被加数低地址 出口:(R0)指向结果的高字节,低位放在低地址,高位放在高地址. NADD: MOV R7,#03H CLR C NADD1: MOV A,@R0 ADDC A,@R1 MOV @R0,A INC R0 INC R1 DJNZ R7,NADD1 DEC R0 RET
软件陷阱技术 未使用的中断向量区 假设系统使用 INT0,T0,T1 ORG 0000H START: LJMP MAIN LJMP PGINT0 NOP ; NOP ; LJMP ERR ; 陷阱 4.3 软件抗干扰
LJMP PGT0 NOP NOP LJMP ERR LJMP PGT1 NOP NOP LJMP ERR NOP NOP JMP ERR 陷阱 陷阱 陷阱
未使用的大片ROM 如果ERR在30H开始的地址单元 ,可用00 00 20 00 30,即: NOP NOP LJMP ERR 表格 在表格最后安排陷阱程序 程序 在跳转指令处,正常执行不会继续执行,可以安排陷阱程序
看门狗 当程序弹飞到一个临时构成的死循环中,软件陷阱就没有作用了,要用程序运行监视系统 1.本身能独立工作,基本不依赖CPU 2.CPU在一个固定时间间隔内和该系统打一次交道(喂一次狗) 3.当CPU陷入死循环时能及时发觉并复位系统 注:8096和增强型8051系统中已内嵌Watchdog
当系统陷入死循环后,只有用比这个死循环更高级的中断子程序才能夺走CPU控制权,可用一个定时器来做Watchdog,它的溢出中断设为高优先级中断当系统陷入死循环后,只有用比这个死循环更高级的中断子程序才能夺走CPU控制权,可用一个定时器来做Watchdog,它的溢出中断设为高优先级中断 例如 T0作Watchdog,定时为16ms 初始化: MOV TMOD,#01H SETB ET0 SETB PT0 MOV TH0,#0B1H MOV TL0,#0E0H SETB TR0 SETB EA Watchdog启动后,每次间隔小于16ms执行一条“MOV TH0,#0E0H”,可暂时喂饱. 当程序陷入死循环,16ms产生一次T0中断,从而跳出死循环。
ORG 0000H AJMP MAIN ORG 000BH LJMP TOP MAIN: MOV SP,#60H MOV PSW,#00H MOV SCON,#00H …. MOV IE,#00H MOV IP,#00H MOV TMOD,#01H LCALL DOG ;调用WDOG …. DOG: MOV TH0,#0B1H MOV TL0,#0E0H SETB TR0 RET TOP: POP ACC ;修改栈指针 POP ACC CLR A PUSH ACC PUSH ACC ;将返回地址变成0000h,实现复位 RETI