【学习课件】第4章汇编程序设计_第1页
【学习课件】第4章汇编程序设计_第2页
【学习课件】第4章汇编程序设计_第3页
【学习课件】第4章汇编程序设计_第4页
【学习课件】第4章汇编程序设计_第5页
已阅读5页,还剩75页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第4章MCS-51汇编语言程序设计 4.1简单程序设计4.2分支程序设计4.3循环程序设计4.4散转程序设计4.5子程序和参数传递方法4.6查表程序设计4.7数制转换习题与思考题程序设计是为了解决某一个问题而将指令有序地组合在一起的过程。 程序有简有繁, 但复杂程序往往是由简单的基本程序所构成的。 本章将通过一些基本程序, 介绍部分常用的程序设计方法。 程序设计的过程大致可以分为以下几个步骤: (1) 编制要解决问题的程序框图。 (2) 确定数据结构、 算法、 工作单元、 变量设定。 (3) 根据所用计算机的指令系统, 按照已编制的程序框图用汇编语言编制出源程序。 (4) 将编制的程序在计算机

2、上调试, 直至实现预定的功能。一、汇编程序功能 源程序 (汇编指令程序) 汇编 目标程序(机器码指令程序) 汇编指令与机器码指令有一一对应的关系。汇编程序是一种翻译程序,将源程序翻译成目标程序。 二、汇编程序的汇编过程 汇编有两种方法:手工汇编、机器汇编。 1、手工汇编:第一次汇编:确定地址,翻译成各条机器码,字符标号原样写出;第二次汇编:标号代真,将字符标号用所计算出的具体地址值或偏移量代换。 源程序 目标程序 地址 ORG 1000H START:MOV R0,2FH MOV R2,#00H MOV A,R0 MOV R3,A INC R3 SJMP NEXT LOOP:INC R0 CJ

3、NE R0,#44H,NEXT INC R2 NEXT:DJNZ R3,LOOP MOV 2AH,R2 SJMP $ END 第一次汇编第二次汇编1000 A82F1002 7A001004 E61005 FB1006 0B1007 80NEXT1009 08100A B644NEXT100D 0A100E DBLOOP1010 8A2A1012 80FEA82F7A00E6FB0B800508B644010ADBF98A2A80FE2、机器汇编两次扫描过程。第一次扫描:检查语法错误,确定符号名字; 建立使用的全部符号名字表; 每一符号名字后跟一对应值(地址或数)。第二次扫描:是在第一次扫描基

4、础上,将符号地址转换成 地址(代真); 利用操作码表将助记符转换成相应的目标码。 三、伪指令 伪指令是告诉汇编程序,如何汇编源程序的指令。 伪指令既不控制机器的操作,也不能被汇编成机器代码, 故称为伪指令。 1、起始地址伪指令 ORG ORG addr16 用于规定目标程序段或数据块的起始地址, 设置在程序开始处。 2、汇编结束伪指令 END 告诉汇编程序,对源程序的汇编到此结束。 一个程序中只出现一 次,在末尾。 3、赋值伪指令 EQU 告诉汇编程序,将汇编语句操作数的值赋予本语句的标号。 格式: 标号名称 EQU 数值或汇编符号 “标号名称”在源程序中可以作数值使用,也可以作数据地址、 位

5、地址使用。 先定义后使用,放在程序开头。4、定义字节伪指令 DB 告诉汇编程序从指定的地址单元开始,定义若干字节存储单 元并赋初值。 格式: 标号: DB 字节数据或字节数据表例、 ORG 1000H PIOI:DW 7654H,40H、12、AB 6、数据地址赋值伪指令 DATA 将表达式指定的数据地址赋予规定的字符名称 格式: 字符名称 DATA 表达式注:该指令与EQU指令相似,只是,可先使用后定义, 放于程序开头、结尾均可。5、定义字伪指令 DW 从指定地址开始,定义若干个16个位数据,高八位存入低地址;低八位存入高地址。7、定义空间伪指令 DS 从指定地址开始,保留由表达式指定的若干

6、字节空间作 为备用空间。 格式: 标号: DS 表达式例2、 ORG 1000H DS 0AH DB 71H,11H,11H ;从100BH开始存放 ;71H11H、11H。 注:DB、DW、DS 只能用于程序存储器; 而不能用于数据存储器。 8、位地址赋值伪指令 BIT将位地址赋予规定的字符名称。格式: 字符名称 BIT 位地址 例3、 X1 BIT P12 相当于 X1 EQU 92H 程序设计有时是一件很复杂的工作,但往往有些程序结构是很典型的。采用结构化编程时,有规律性极强、简单清晰、容易读写、可靠性高等特点。根据结构化程序设计的观点,功能复杂的程序结构由基本算法结构组成,基本结构有三

7、种:顺序结构、循环结构和分支结构。 语句 3语句 2顺序结构 入口语句 1 出口分支结构入口条件满足否? 分支 1 出口YN 分支 2循环结构入口 处理 修改条件条件满足否?Y 出口N4.1简单程序设计简单程序又称顺序程序。 计算机是按指令在存储器中存放的先后次序来顺序执行程序的。 【例4-1】两个8位的无符号数相加的和仍是8位。 设内部 RAM的40H、 41H单元中分别存放8位数N1、 N2, 两数相加的结果送42H单元。 程序如下: AD1: MOV R0, #40H ; 设R0为数据指针 MOV A, R0 ; 取N1 INC R0 ; 修改指针 ADD A, R0 ; N1 + N2

8、 INC R0 MOV R0, A ; 存结果 END【例4-2】将两个半字节数合并成一个一字节数。 设内部RAM的40H、 41H单元中分别存放着8位二进制数, 要求取出两个单元中的低半字节, 并将其合并成一个字节后存放在42H单元。 程序如下: START: MOV R1, #40HMOV A, R1 ANL A, #0FH ; 取第一个半字节 SWAP A ; 移至高4位 INC R1 XCH A, R1 ; 取第二个字节 ANL A, #0FH ; 取第二个半字节 ORL A, R1 ; 拼字 INC R1 MOV R1, A ; 存放结果 END以上程序均采用了寄存器寻址方式, 可以

9、方便地取数、 存数。 例4-2 中用XCH A, R1指令, 既取出了数, 又保存了中间结果。 4.2分支程序设计在处理实际事务中, 只用简单程序设计的方法是不够的, 因为大部分程序总包含有判断、 比较等情况, 程序将根据判断、 比较的结果转向不同的分支。 下面举两个分支程序的例子。 【例4-3】两个无符号数比较大小。 设存储单元ST1和ST2中存放着两个不带符号的二进制数, 找出其中的大数存入ST3单元中。 流程图如图4-1所示。 图4-1两个无符号数的比较流程 程序如下: ST1: EQU 8040HORG 8000HSTART1: CLR C ; 进位位清0 MOV DPTR, #ST1

10、 ; 设数据指针 MOVX A, DPTR ; 取第一个数 MOV R2, A ; 暂存于R2 INC DPTR MOVX A, DPTR ; 取第二个数 SUBB A, R2 ; 两数比较 JNC BIG1 XCH A, R2 ; 第一个数大BIG0: INC DPTR MOVX DPTR, A ; 存大数 RET BIG1: MOVX A, DPTR ; 第二个数大 SJMP BIG0 END上面程序中, 用减法指令SUBB来比较两数的大小。 由于这是一条带借位的减法指令, 因此在执行该指令前, 应先把进位位清0。 用减法指令通过借位(CY)的状态判别两数的大小, 是两个无符号数比较大小时

11、常用的方法。 设有两数x, y, 执行x-y, 当xy 时, 结果无借位产生, 则CY=0; 反之, 则CY=1, 表示x0, 1A SJMP FINISHSUL: MOV A, #0 SJMP FINISH NEG1: MOV A, #FFH ; x0, -1A FINISH: MOV DPTR, #BUF MOVX DPTR, A END4.3循环程序设计在程序设计中, 只有简单程序和分支程序是不够的。 因为简单程序每条指令只执行一次, 而分支程序则根据条件的不同, 会跳过一些指令, 执行另一些指令。 它们的特点是, 每一条指令至多执行一次。 在处理实际事务时, 有时会遇到多次重复处理的问

12、题, 用循环程序的方法来解决就比较合适。 循环程序中的某些指令可以反复执行多次。 采用循环程序, 可以缩短程序, 节省存储单元。 当重复次数越多时, 循环程序的优越性就越明显。 但是程序的执行时间并不节省。 由于要有循环准备、 结束判断等指令, 速度要比简单程序稍慢些。 循环程序一般由五部分组成: (1) 初始化部分: 为循环程序做准备。 如设置循环次数计数器的初值、 地址指针置初值、 为循环变量赋初值等。(2) 处理部分: 为反复执行的程序段, 是循环程序的实体。 (3) 修改部分: 每执行一次循环体后, 对指针作一次修改, 使指针指向下一数据所在位置, 为进入下一轮处理做准备。 (4) 控

13、制部分: 根据循环次数、 计数器的状态或循环条件等检查循环是否能继续进行, 若循环次数到或循环条件不满足时, 应退出循环, 否则继续循环。 通常(2)、 (3)、 (4)部分又称为循环体。 (5) 结束部分: 分析及存放执行结果。 循环程序的结构一般有两种形式: (1) 先进入处理部分, 再控制循环, 即至少执行一次循环体, 如图4-3(a)所示。 (2) 先控制循环, 后进入处理部分, 即根据判断结果控制循环的执行与否, 有时可以不进入循环体就退出循环程序, 如图4-3(b)所示。 图4-3循环程序的结构形式 循环结构的程序, 不论是先处理后判断, 还是先判断后处理, 其关键是控制循环的次数

14、。 根据需解决问题的实际情况, 对循环次数的控制有多种: 循环次数已知的,用计数器控制循环; 循环次数未知的, 可以按条件控制循环, 也可以用逻辑尺控制循环。 循环程序又分单循环程序和多重循环程序。 下面举例说明循环程序的使用。 1. 单循环程序1) 循环次数已知的循环程序下面举几个循环次数已知的循环程序例子。【例4-5】工作单元清0。在程序设计时, 有时需要将存储器中的部分地址作为工作单元, 存放程序执行的中间值和结果。 工作单元清0工作常常放在程序的初始化部分中。 设有50个工作单元, 其首址存放在DPTR中, 循环次数存放在R2寄存器中, 每执行一次循环, R2的内容减1, 直至R2=0

15、时, 循环程序结束。 流程图见图4-4 图4-4工作单元清0流程图 CLEAR: CLR A MOV R2, #32H ; 置计数值LOOP: MOVX DPTR, A INC DPTR ; 修改地址指针 DJNZ R2, LOOP ; 控制循环 END本例中循环次数是已知的。 用R2作循环次数计数器, 用DJNZ指令修改计数器值, 控制循环的结束与否。 【例4-6】多个单字节数据求和。 已知有n个单字节数据, 依次存放在内部RAM的40H单元开始的连续单元中, 要求把计算结果存入R2、 R3中(高位存R2, 低位存R3)。 流程图见图4-5 。 图4-5多个单字节数据求和流程图 程序如下:

16、NUM EQU 0AHORG 8000H SAD: MOV R0, #40H ; 设数据指针 MOV R5, #NUN ; 计数值0AHR5 SAD1: MOV R2, #0 ; 和的高8位清0 MOV R3, #0 ; 和的低8位清0 CLR A LOOP: ADD A, R0; 取加数 MOV R3, A ; 存和的低8位 JNC LOP1 INC R2 ; 有进位, 和的高8位+1 LOP1: INC R0 ; 指向下一数据地址 DJNZ R5, LOOP END 上述程序中, 用R0作间址寄存器, 每做一次加法, R0加1, 数据指针指向下一数据地址, R5为循环次数计数器, 控制循环

17、的次数。 2) 循环次数未知的循环程序以上介绍的几个循环程序例子, 它们的循环次数是已知的, 适合用计数器置初值的方法。 而有些循环程序事先不知道循环次数, 不能用以上方法。 这时需要根据判断循环条件的成立与否, 或用建立标志的方式控制循环程序的结束。 【例4-7】测试字符串长度。 设有一串字符依次存放在内部RAM的从50H单元开始的连续单元中。 该字符串以回车符为结束标志。 测字符串长度程序, 即将该字符串中的每一个字符依次与回车符相比; 若比较不相等, 则统计字符串长度的计数器加1; 若比较相等, 则表示该字符串结束, 计数器中的值就是字符串的长度。 程序如下: CONT: MOV R2,

18、 #0FFHMOV R0, #4FH ; 数据指针R0置初值LOOP: INC R0INC R2CJNE R0, #0DH, LOOPEND 待测字符以ASCII码形式存放在RAM中, 回车符的ASCII码为0DH, 程序中用一条CJNZ R0, #0DH, LOOP指令实现字符比较及控制循环的任务, 当循环结束时, R2的内容为字符串长度。 3) 用逻辑尺控制循环次数的循环程序在实际应用中, 有时并不要求按一定的固有顺序执行循环处理, 而要求处理部分是不规则的循环过程。 如调用处理部分的子程序PRG0、 PRG1共8次。 调用顺序为: 第1、 3、 4、 7次是调用PRG1; 其余是调用PR

19、G0。 程序的设计方法是: 设总的调用次数为循环次数, 并且另设一个标志, 用来识别调用哪个子程序。 两个子程序可以用0和1两种逻辑状态识别, 如用0状态表示调用PRG0, 用1状态表示调用PRG1。 由于总共调用8次, 因此用一个寄存器的8位作为8个标志位, 按调用子程序的顺序, 把0、 1存放在寄存器的不同位上。 当执行程序时, 由寄存器的第0位或第7位起逐位测试, 根据此位的状态决定调用哪个子程序。 因此该寄存器好像一把“尺”, 它的内容犹如“尺”的“刻度”, 作为识别调用子程序的标志, 人们称它为“逻辑尺”。 “逻辑尺”的长宽视需要而定, 一个字节不够用, 可以把相邻的字节串联起来,

20、或者设定n把“逻辑尺” 。 【例4-8】逻辑尺使用。设R0为原始数首地址, R1存放结果首地址, R3为逻辑尺, 流程图如图4-6所示。 图4-6逻辑尺程序流程图 程序如下: PRG0 EQU 8360H PRG1 EQU 8200H ORG 8000H TEST: MOV R2, #08H ; 逻辑尺长度 MOV R3, #10110010B ; 设定逻辑尺 LOOP:MOV A, R0 ; 取数据 XCH A, R3 RLC A ;左移, 读尺刻度 XCH A, R3 JC LOOP1 ; 转调用PRG1 LCALL PRG0 ; 是0, 调用PRG0 SJMP RELTLOOP1: LC

21、ALL PRG1 RELT: MOV R1, A ; 存结果 INC R0 INC R1 DJNZ R2, LOOP ;R20, 继续循环END 2. 多重循环程序如果在一个循环体中又包含了其他的循环程序, 即循环中还套着循环, 则这种程序称为多重循环程序。 【例4-9】10 s延时程序。 延时程序与MCS-51执行指令的时间有关, 如果使用6 MHz晶振, 则一个机器周期为2 s, 计算出执行一条指令以及一个循环所需要的时间, 给出相应的循环次数, 便能达到延时的目的。 程序如下: DEL: MOV R5, #100DEL0: MOV R6, #200DEL1: MOV R7, #248DE

22、L2: DJNZ R7, DEL2 ;248*2+4 DJNZ R6, DEL1 ; (248*2+4)*200+4 DJNZ R5, DEL0 ; (248*2+4)*200+4)*100+4 RET 上例延时程序实际延时为10.000 406 s。 它是一个三重循环程序, 利用程序嵌套的方法对时间实行延迟是程序设计中常用的方法。 使用多重循环程序时, 必须注意以下几点: (1) 循环嵌套必须层次分明, 不允许产生内外层循环交叉。(2) 外循环可一层层向内循环进入, 结束时由里往外一层层退出。 (3) 内循环体可以直接转入外循环体, 实现一个循环由多个条件控制的循环结构方式。 3. 循环程序

23、应用举例 1) 不带符号数的多字节加法在处理多字节运算时, 应注意低字节向高字节的进位(或借位)(用进位CY判别, 当CY=0时, 表示无进位或借位, 反之则表示有进位或借位)。 在进行不带符号的单字节二进制数加减运算时, 用进位CY判别数的溢出与否。 【例4-11】两个多字节数P、 Q均以低字节在前, 高字节在后的次序, 分别存放在由R0、 R1指出的内部RAM中, 相加后存入P数据区, 见图4-8。 图4-8RAM数据存储示意 程序如下: N1 EQU 0AHORG 8000HSTART1: CLR C ; 清进位 MOV R2, #N1 ; 取字节数MADD: MOV A, R0 ; 取

24、加数(一个字节) ADDC A, R1; 两数相加(由低字节开始) MOV R0, A INC R0 INC R1 DJNZ R2, MADD ; 两数加完? JC ERR ; 和字节数大于n, 则溢出错 RETERR: END 上例中若将ADDC A, R1指令改为SUBB A, R1指令, 则该程序就是多字节减法程序。 无符号数的减法运算, 被减数必须大于减数。 不带符号的十进制数加法程序的设计思想与上例相同。 MCS-51指令系统中没有直接的十进制数加法指令, 要做十进制BCD码加减运算, 只要在加、 减指令后跟一条DA A指令, 即可使运算结果成为十进制数的形式。 4.4散转程序设计散

25、转程序是分支结构程序中的一种并行分支程序。它是根据某种输入或运算结果,分别转向各个处理程序。在MCS-51单片机中,散转指令为JMP A+DPTR,它按照程序运行时决定的地址执行间接转移指令。例:根据R7中的内容,转向各个子程序。说明:(1) 采用AJMP即把PC指向子程序的起始地址;(2) R7+R7=R72,与AJMP的机器码匹配,因n128,不会进位;(3) 如用LJMP,则需R73,程序需要作相应修改。图4.2 散转程序流程图4.5子程序和参数传递方法在解决实际问题时,经常会遇到一个程序中多次使用同一个程序段,例如延时程序、查表程序、算术运算程序段等功能相对独立的程序段。 为了节约内存

26、,我们把这种具有一定功能的独立程序段编成子程序。调用程序称为主程序,被调用的程序称为子程序。调用子程序有几个优点: (1) 避免了对相同程序段的重复编制。 (2) 简化程序的逻辑结构, 同时也便于子程序调试。 (3) 节省存储器空间。 MCS-51指令系统中, 提供了两条调用子程序指令: ACALL及LCALL, 并提供了一条返回主程序的指令RET。 子程序的编写和调用应该做到:(1) 标准化。注释中应该注明程序名、功能、入口、出口和所占用的寄存器和存储单元。(2) 现场保护。 如果在调用前,程序已经使用了某些存储单元或寄存器,在调用时,这些寄存器和存储单元又有其它用途,就应该先把这些单元和寄

27、存器中的内容压入堆栈进行保护。调用完后,再从堆栈中弹出,加以恢复。如果有较多的寄存器需要保护,应使主程序和子程序使用不同的寄存器组。例1:从内部RAM 22H单元开始存有一个无符号数数据块,长度n存于21H中。求出数据块中的最小数,存于20H中。ORG 0030H MOV R0,#22H;数据块起始地址 MOV R1,21H;数据个数n MOV 20H,#0FFH;初始化最小数为0FFHLOOP:MOV A,R0;取新数 INC R0 ;为取下一个新数做准备 CJNE A,20H,LOOP1;与原最小数比较LOOP1:JNC NEXT ;大于等于,原最小数保留 MOV 20H,A ;小于,改变

28、最小数NEXT:DJNZ R1,LOOP ;判断循环 END4.6查表程序设计查表程序是一种常用程序, 它广泛使用于LED显示器控制、 打印机打印以及数据补偿、 计算、 转换等功能程序中, 具有程序简单、 执行速度快等优点。 查表, 就是根据变量x与y的关系y=f(x), 在表格中查找y。 MCS-51系列单片机专门提供了两条查表指令:MOVC A,A+DPTRMOVC A,A+PC例1:设有一个巡回检测报警装置,需对16路输入进行控制,每路有一个最大允许值(为双字节)。控制时需根据测量的通道,找出每路的最大值,高、低8位分放于R3、R4。ORG 0000HSTART:MOVA,R2;待查通道

29、数送A ADDA,R2;待查通道数乘2,与数据表中的地址相配 MOV R3,A;保存通道数 MOV DPTR, #ADDR8 ;表格首址送DPTR MOVC A,A+DPTR;查出对应通道的最大允许值高位字节 INC R3;为指向下一个地址单元做准备 XCH A,R3 MOVC A,A+DPTR;查出对应通道的最大允许值低位字节 MOV R4,A;存入R4 ADDR8:DW 1520H,3721H,4264H,7850H;最大允许值表 DW 3484H,3265H,8830H,9947HEND例2 在程序中定义一个09的平方表,利用查表指令找出累加器A=05H的平方值。 (1) 题意分析 所谓

30、表格是指在程序中定义的一串有序的常数,如平方表、字型码表、键码表等。因为程序一般都是固化在程序存储器(通常是只读存储器ROM类型)中,因此可以说表格是预先定义在程序的数据区中,然后和程序一起固化在ROM中的一串常数。 查表程序的关键是表格的定义和如何实现查表。 (2) 汇编语言源程序。 ORG0000H MOV DPTR, #TABLE ;表首地址DPTR(数据指针) MOVA,#05 ;05A MOVCA,A+DPTR;查表指令,25A,A=19H SJMP$;程序暂停 TABLE:DB0,1,4,9,16,25,36,49,64,81;定义09平方表 END4.7数制转换日常生活中, 人们

31、习惯用十进制数进行各种运算, 但在计算机内部却只能用二进制数运算。 用二进制编码的十进制数就是能把十进制数转换成适合计算机使用的一种数制, 称为BCD码。 数制转换、 代码转换在使用计算机时是必不可少的部分。 下面将介绍几个常用的转换程序。 3 十六进制数转换成七段代码七段发光二极管显示一个数时, 该数对应的代码为七段代码, 图4-15为七段代码显示器的共阳极接法, 当相应段加上“0”电平时, 该段亮。 图4-15七段数码管显示器结构 由表4-1的七段代码表看出, 七段代码和数字之间没有什么规律, 所以适合用查表的方法进行转换。 先把七段代码按0F的顺序存入存储器, 表首地址为TABS。 利用表首地址相加待转换值, 即得到对应代码所在的单元地址, 从中取得需要的代码。 表 4-1七 段 代 码

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论